开启tidb_enable_non_prepared_plan_cache参数之后,缓存的数量远超tidb_session_plan_cache_size且内存持续上涨,关闭该参数之后,内存和缓存数量依旧上涨

【 TiDB 使用环境】生产环境
【 TiDB 版本】7.5.3

【遇到的问题:问题现象及影响】

在迁移MySQL数据到TIDB之后遇到慢查看到存在一些 “解析耗时”或者“生成执行计划耗时” 导致的慢查,

然后查阅官方文档打开tidb_enable_non_prepared_plan_cache参数并调整tidb_session_plan_cache_size到200;同时tidb_plan_cache_max_plan_size从2M增加10M(刚开始没有理解这个参数,调的有点,后来减少到5M,恢复到2M)

发现内存持续上涨

server内存上涨是这里的 session-plan-cache 上涨导致的

然后在 15:29的时候关闭了 tidb_enable_non_prepared_plan_cache参数,且修改的值都改回默认是(包括另外一个没有使用的server节点也都确保修改会默认值了)


XXXX@192.168.1.30:4002 15:19:  [shop] >SET tidb_enable_non_prepared_plan_cache = OFF;
Query OK, 0 rows affected (0.00 sec)


XXXX@192.168.1.30:4002 16:01:  [shop] >show variables like 'tidb_plan_cache_max_plan_size';
+-------------------------------+---------+
| Variable_name                 | Value   |
+-------------------------------+---------+
| tidb_plan_cache_max_plan_size | 2097152 |
+-------------------------------+---------+
1 row in set (0.00 sec)

XXXX@192.168.1.30:4002 16:02:  [shop] >show variables like 'tidb_enable_non_prepared_plan_cache';
+-------------------------------------+-------+
| Variable_name                       | Value |
+-------------------------------------+-------+
| tidb_enable_non_prepared_plan_cache | OFF   |
+-------------------------------------+-------+
1 row in set (0.00 sec)

XXXX@192.168.1.30:4002 16:02:  [shop] >show variables like 'tidb_session_plan_cache_size';
+------------------------------+-------+
| Variable_name                | Value |
+------------------------------+-------+
| tidb_session_plan_cache_size | 10    |
+------------------------------+-------+
1 row in set (0.00 sec)

XXXX@192.168.1.30:4002 16:02:  [shop] >show variables like 'tidb_prepared_plan_cache_size';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| tidb_prepared_plan_cache_size | 10    |
+-------------------------------+-------+
1 row in set (0.00 sec)

后来甚至把 tidb_session_plan_cache_size 从100降到10也是没有解决问题。

但是实际上 session-plan-cache 和 server的内存都还在持续上涨。

请问这个问题如何修复?

这个缓存多久失效呢?

尝试ADMIN FLUSH [SESSION | INSTANCE] PLAN_CACHE,试试呢?

你这30g增长的内存里面只有2g是缓存的问题。
其他的应该都不是。go这种带内存回收机制的,如果你的机器内存很足,有垃圾也不会着急回收的。等着不够用了再去回收。

另外non-prepared缓存对你来说还挺合适的,居然有3-40%的命中率。反而是prepared的命中率非常糟糕,不如直接关了。

长链接?

1、30g增长的内存里面只有2g是缓存的问题
这个你是从哪里判断的呀?
倒是这里内存监控显示增长很快,但是通过主机内存监控看到波动确实不大呢

2、3-40%的命中率
大佬这个数据又是怎么得到的呀

从历史监控看 prepared的确实使用的极少,之前也没有怎么关注过这块的问题

3、如果你的机器内存很足,有垃圾也不会着急回收的。等着不够用了再去回收。

这里这个缓存清理只能是等待server节点本身内存超限的时候才会清理么?

嗯嗯,我了解下这个命令的使用场景和用法

不是不是,就是non-prepared 造成的

还发现个问题,第一次关闭这个参数之后,查看的时候确实是OFF了,如问题中描述的。但是后来再次查看的时候发现这个参数又是ON了,再次尝试关闭的时候,,监控图上才体现 non-prepared queries 开始下降了

从server节点日志中只能看到最开始的 开启和 16:15 (SET @@global.tidb_enable_non_prepared_plan_cache = OFF) 的再次关闭记录

tidb-2024-12-11T15-06-51.783.log:[2024/12/11 14:45:07.987 +08:00] [INFO] [set.go:169] ["set global var"] [conn=1774594746] [name=tidb_enable_non_prepared_plan_cache] [val=ON]
tidb-2024-12-11T16-42-22.806.log:[2024/12/11 16:15:14.391 +08:00] [INFO] [set.go:169] ["set global var"] [conn=1775523008] [name=tidb_enable_non_prepared_plan_cache] [val=OFF]

第二次的 set tidb_enable_non_prepared_plan_cache = OFF 没有在日志中找到,
而且最终一次生效的 set tidb_enable_non_prepared_plan_cache = OFF 没有在日志中找到

kfzdba@192.168.1.30:4002 16:34:  [(none)] >show variables like 'tidb_enable_non_prepared_plan_cache';
+-------------------------------------+-------+
| Variable_name                       | Value |
+-------------------------------------+-------+
| tidb_enable_non_prepared_plan_cache | ON    |
+-------------------------------------+-------+
1 row in set (0.00 sec)

kfzdba@192.168.1.30:4002 16:34:  [(none)] >
kfzdba@192.168.1.30:4002 16:34:  [(none)] >set tidb_enable_non_prepared_plan_cache = OFF;
Query OK, 0 rows affected (0.00 sec)

另外第一次开启也是session级别,时间是14:47 ,和日志的14:45也有时差

kfzdba@192.168.1.30:4002 14:47:  [(none)] >SET tidb_enable_non_prepared_plan_cache = ON;
Query OK, 0 rows affected (0.00 sec)

有人知道 tidb 默认session级别的变量更新是不记录日志吗?

这里。

这里non-prepared命中400多,未命中600多。

别猜了,从dashboard里面导出一个内存dump看看,什么东西占用高。

https://docs.pingcap.com/zh/tidb/stable/dashboard-profiling#开始性能分析
这个页面选heap。看看存了啥。

image

就是这部分的dump。

session级设置关闭plancache的意思就是这个session不用。
其他的连接建立的时候从global级读取这个变量还是会使用plancache。

另外这个问题需要开发注意一下的,不用prepared用不上plancache还是小问题。
最大的问题是,不用prepared sql,那只能字符串拼接sql。及其容易出现sql注入。
一个没注意,被sql注入攻击了,那就玩完了。

https://juejin.cn/post/6986531291659255838

2 个赞

nice~ 大佬就是大佬

嗯嗯确实是个风险,确实需要和开发反馈下。

能帮忙分析看看heap文件,是不是因为开启了 non_prepared_plan_cache 之后,导致的统计信息增多导致的嘛
heap_tidb_192.168.1.30_4002_4206134845.proto.zip (10.7 MB)

确实是统计信息相关的占用高。是否plancache相关我说不好,你是从哪里看到这种说法的?我也想看看。

如果这台当时就是在运行analyze的话,我感觉这个是主要原因,可以调整一下统计信息收集的时间。看看是否会好一些。

因为之前另外一个老集群OOM挂过, 产生的OOM heap文件分析当时内存最大的也是 statistics接口。 那会之前调整过慢查的阈值,分析是因为导致慢查增多,然后关联的统计信息增多导致的oom,再把阈值调大之后就慢慢恢复了。

和这次heap分析有点类似。所以怀疑也是和统计信息收集关系,我先调整了慢查,缓解了不怎么快速涨了。

”调整一下统计信息收集的时间“ 这个怎么调整呢?

另外发现个问题 tidb_enable_non_prepared_plan_cache 这个参数的修改有问题呢,昨天修改了三次最终才立即生效。

今天13:07 我又关闭了,但是从监控上看没有”完全生效“ 似的

你关闭命令有global吗

1 个赞