【求助贴】tidb server节点内存优化

【TiDB 使用环境】生产环境
【TiDB 版本】8.5.1
【部署方式】自建机房私有化部署
【操作系统/CPU 架构/芯片详情】centos7.9
【机器部署详情】混合部署
【集群数据量】单节点tikv 500G
【集群节点数】7
【遇到的问题:问题现象及影响】
在自建机房部署tidb集群,tidb和pd是混布的,单节点最大内存47GB,由于之前出现过节点tidb server因OOM导致重启,故设置tidb_server_memory_limit为30GB;随着使用的时间越来越长,集群中heapinuse的大小只增不减,查询监控发现,现在因为这个设置,会经常导致运行中的sql被kill掉,而影响业务(报错见下面ERROR报错的日志处)。想请问这种情况的优化方式是什么?以及heapinuse为何会占用这么大内存,何时会释放。
【资源配置】进入到 TiDB Dashboard -集群信息 (Cluster Info) -主机(Hosts) 截图此页面

【复制黏贴 ERROR 报错的日志】

2026-02-04 01:32:08 (UTC+08:00)TiDB 1.1.1.1:4000[coprocessor.go:1389] ["[TIME_COP_PROCESS] resp_time:425.120824ms txnStartTS:464031529392668674 region_id:11542710 store_addr:1.1.1.1:20160 stats:Cop:{num_rpc:1, total_time:425.1ms} kv_process_ms:277 kv_wait_ms:0 kv_read_ms:122 processed_versions:50144 total_versions:53086 rocksdb_delete_skipped_count:5168 rocksdb_key_skipped_count:108711 rocksdb_cache_hit_count:510 rocksdb_read_count:756 rocksdb_read_byte:1946526"] [conn=827668692] [session_alias=]
2026-02-04 01:32:09 (UTC+08:00)TiDB 1.1.1.1:4000[servermemorylimit.go:159] ["global memory controller tries to kill the top1 memory consumer"] [conn=827668692] ["sql digest"=74810cb713eae918c74284fbc62d75fd2a4cffe9a5038238f53e3b65191ad948] ["sql text"="select  Rec_id\n                                    ,Defect\n                                    ,Stoc"] [tidb_server_memory_limit=32212254720] ["heap inuse"=32224280576] ["sql memory usage"=227603297]
2026-02-04 01:32:09 (UTC+08:00)TiDB 1.1.1.1:4000[sqlkiller.go:61] ["kill initiated"] ["connection ID"=827668692] [reason="[executor:8176]Your query has been cancelled due to exceeding the allowed memory limit for the tidb-server instance and this query is currently using the most memory. Please try narrowing your query scope or increase the tidb_server_memory_limit and try again.[conn=827668692]"]
2026-02-04 01:32:09 (UTC+08:00)TiDB 1.1.1.1:4000[sqlkiller.go:128] ["global memory controller, NeedKill signal is received successfully"] [conn=827668692]

tidb_server_memory_limit=30GB
内存不足,内存占用最大的sql被杀掉了
默认 GOGC=100
这个太大了,改50. 这样就不会内存不足了 export GOGC=50

47GB * 80% ≈ 37.6GB , 调大一点比较安全

连接数有几十万?

连接数没有那么大 :joy:平时只在200-500

之前默认就是80%,但是按这个值,tidb-server进程会发生OOM,我想知道的是,这个heapinuse为啥一直不释放呢,越跑越多,给再多内存也没用啊 :joy:

连接数这么大吗


这还好吧。。。

  • tidb_server_memory_limit 设置过严(30GB),但业务负载导致内存占用接近阈值时,SQL Killer 会频繁中断查询,影响业务。
  • 内存未及时释放:TiDB 的内存分配器(Jemalloc)会缓存空闲内存,导致 heapinuse 持续高位,即使查询结束也不会立即归还系统。

高手啊

学习了

这个问题你描述得非常完整,其实这是 TiDB 在混布 + 严格内存上限场景下非常典型的一类问题,不是单点 bug,而是内存模型 + 使用方式 + 配置策略叠加的结果。我分几块给你讲清楚「为什么会这样」以及「能怎么优化」,尽量给到可落地的方案。

如果业务允许,尽量将 TiDB 和 PD 拆分部署,避免资源争抢,这样内存配置会更从容

Memory Usage和 Top SQL也看一下

问题原因已找到,感觉tidb的老师,帮忙分析,谢谢。
经分析,应该是命中了issue planner: prevent pseudo-stats from dominating the Stats Cache · Issue #60137 · pingcap/tidb · GitHub

【触发场景】
是用户频繁执行 CREATE/DROP 临时表,每个临时表都会构造一份 Pseudo stats 放入 stats cache,并且不会随着 DROP table 清理 stats,导致这部分统计信息占用越来越多 cache。

master 版本做了部分优化,可以减少大概50%内存,但是没有带入 v8.5 stats: optimize memory footprint of pseudo stats table by Tristan1900 · Pull Request #63160 · pingcap/tidb · GitHub

【Workaround】

1、将临时表改造为普通表

2、调小 tidb_stats_cache_mem_quota

1 个赞

照理说,pd、kv和tidbserver混合部署不会有什么影响,但是如果是生产环境的话最好分开,这样解耦效果好一些