TiDB慢SQL内存和计算节点暴涨内存OOM不一致问题

生产环境tidb 版本v7.5.4

Your MySQL connection id is 3683000214 Server version: 8.0.11-TiDB-v7.5.4 TiDB Server

生产配置

4c 16g tidb+pd,12c 96g tikv存储,业务低峰期,整体QPS不高

tidb计算节点内存上涨和服务器监控内存上涨一致

tidb计算发生OOM

内存上涨近3倍持续几分钟时间后,两个节点节点先后发生OOM

/tmp/1101_tidb目录下也没有记录相关慢sql,推断也可能是/tmp目录文件刚好超过10天被系统自动清理了

慢sql日志分析

统计该tidb这2分钟内慢sql日志

sed -n ‘/^# Time: 2024-11-26T08:00./,/^# Time: 2024-11-26T08:02./p’ tidb_slow_query-2024-11-26T08-04-37.802.log >/rebate_tidb_slow_log

2分钟内慢sql日志总数量110个

grep “Mem_max” /rebate_tidb_slow_log | cut -d":" -f2 | sort -nr | wc -l

110

计算出慢sql日志总内存消耗为1063 MB ,远小于tidb计算节点内存上涨的6G内存

grep “Mem_max” /rebate_tidb_slow_log | cut -d":" -f2 | awk ‘{ sum += $1 } END { print sum/1024/1024 }’
1069.3

grep “Mem_max” /rebate_tidb_slow_log | cut -d":" -f2 | sort -nr

92573710

92573710

92572982

92572982

92572982

84158051

84158051

84158051

84157323

84157323

84157323

84157323

1757760

1691988

1681956

1681030

1667926

1663216

2分钟内2个计算节点 select慢查询如下,无明显很耗时、内存占用高情况

10分钟内2个计算节点所有慢查询如下,无明显很耗时、内存占用高情况,且慢查询类型都为select,无内部sql任务

相关select sql
SELECT

cs.*

FROM

xxxx cs

WHERE

cs.mart_code = ‘wm’

AND cs.goods_code = ?

AND cs.shop_code IN (

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

?,

? (len :97669);

结束时间拉长到8点10分试试,有可能慢语句占用了内存,但是在8点01分没有结束,慢查询是以执行结束时间统计的。

内存上涨不一定都是慢查询吧,从其他地方找找

  1. 多次的小查询:大量的小查询也可能导致内存消耗增加,尤其是在有大量短生命周期对象被创建和销毁的情况下。
  2. 服务器级别其他服务:服务器上运行的其他服务可能存在内存泄漏问题,或者由于请求过多导致内存资源占用增加。
  3. 系统配置不当:系统配置不当,如缓存策略不合理,也可能导致内存资源的浪费
1 个赞

:+1:楼上回答的非常全面,楼主可以参考一下。

并没有高QPS情况,高并发QPS下内存上涨是能说通;截图补充了10分钟内慢查询没有大耗时,大内存情况

截图补充了10分钟内慢查询没有大耗时,大内存情况,内部sql情况

还有一种情况就是有大查询,但是被kill了。这种的不会记录在慢查询里,需要去日志里查询。慢查询里只记录执行完成的语句,kill的语句不会记录。

比如内存超过限定值时,会被kill
https://docs.pingcap.com/zh/tidb/stable/system-variables#tidb_mem_quota_query

1 个赞

看起来 tidb-server 服务器内存很小?可以考虑试试关闭 go gc tuner:
set global tidb_enable_gogc_tuner=OFF;

从配置上讲 tidb比tikv更吃cpu和内存,你这个配置并不合理,减少tikv内存和c转给tidb

应该是有一个大sql或者全表扫描百万千万级别的表。获取大量数据。最后要么是被kill了要么是已经查出结果了。计算量太大。

这参数我后面再试试;计算16G内存,平时大多数时候tidb-server使用内存低4G左右

配置灵活不了,云主机nvme本地盘12c 96g规格是死的,仅只有一种… tidb-server平时大多数时候内存消耗很低4G左右,

在线改即可,这个影响 go gc 的。尤其在服务器内存比较低的时候,默认开启动态 gc 可能 gc 不过来。

慢 SQL 是在语句结束的时候记录的,可以看下 tidb 的日志,查找问题时间段 expensive 关键字

10号这配置调整为off后,还是出现内存抖增问题了

改了还不行就需要看看 OOM 的 record 了。
tidb deploy目录下,log/oom_record 内容看看。

看是没啥占内存高的SQL
record2024-12-18T08:19:31+08:00]# grep ‘mem_max:’ running_sql
mem_max: 280736 Bytes (274.2 KB)
mem_max: 45294 Bytes (44.2 KB)
mem_max: 25640 Bytes (25.0 KB)
mem_max: 159 Bytes (159 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 280736 Bytes (274.2 KB)
mem_max: 25640 Bytes (25.0 KB)
mem_max: 45294 Bytes (44.2 KB)
mem_max: 159 Bytes (159 Bytes)

record2024-12-18T08:19:31+08:00]# grep ‘mem_max:’ …/record2024-12-18T08:22:09+08:00/running_sql
mem_max: 75856364 Bytes (72.3 MB)
mem_max: 91146 Bytes (89.0 KB)
mem_max: 16482 Bytes (16.1 KB)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 75856364 Bytes (72.3 MB)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 16482 Bytes (16.1 KB)
mem_max: 91146 Bytes (89.0 KB)

record2024-12-18T08:19:31+08:00]# grep ‘mem_max:’ …/record2024-12-18T08:21:05+08:00/running_sql
mem_max: 50571880 Bytes (48.2 MB)
mem_max: 654944 Bytes (639.6 KB)
mem_max: 65696 Bytes (64.2 KB)
mem_max: 65316 Bytes (63.8 KB)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 50571880 Bytes (48.2 MB)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 0 Bytes (0 Bytes)
mem_max: 654944 Bytes (639.6 KB)
mem_max: 65316 Bytes (63.8 KB)
mem_max: 65696 Bytes (64.2 KB)
mem_max: 0 Bytes (0 Bytes)

0 Bytes的不确定文件中SQL内存消耗是否准确

https://docs.pingcap.com/zh/tidb/stable/configure-memory-usage#tidb-server-内存占用过高时的报警 可以具体看下这部分。

内存不一定 100% 准,但是会有一定参考价值。你看看 mem max 几十 MB 的 sql,手动 explain Analyze 看看有没有内存大的情况。因为他这个是当时内存的使用情况参考,不一定是最终内存使用。

手动试explain analyze内存消耗小,running_sql里有些参数化的in多条件查询,可能in条件多耗内存