【 TiDB 使用环境】Poc
【 TiDB 版本】6.3.0
【遇到的问题】 max_prepared_stmt_count
不生效
【复现路径】做过哪些操作出现的问题
set global max_prepared_stmt_count=2;
PREPARE mystmt1 FROM ‘SELECT ? as num FROM DUAL’;
PREPARE mystmt2 FROM ‘SELECT ? as num FROM DUAL’;
PREPARE mystmt3 FROM ‘SELECT ? as num FROM DUAL’;
当前只开了1个会话,观察prometheus中tidb_server_prepared_stmts指标为3。
多次执行后该指标远超过3,但是并未报错。
【问题现象及影响】
max_prepared_stmt_count
- 作用域:GLOBAL
- 是否持久化到集群:是
- 类型:整数
- 默认值:
-1
- 范围:
[-1, 1048576]
- 指定一个会话中
PREPARE
语句的最大数量。 - 值为
-1
时表示不对会话中的PREPARE
语句数量进行限制。 - 如果将变量值设为超过上限
1048576
,则使用上限值1048576
:
为了避免prepare泄露导致内存oom,需要对session级别的prepare进行限制,看到这里有一个max_prepared_stmt_count参数可以对会话的prepare进行限制,但是实际测试中并不生效,具体如下:
从图中可以看到当前的tidb_prepared_statement_count已经超过了2,但是当前会话并没有任何报错或者warnings。
这里有两个问题:
问题1:文档中说该参数值指max_prepared_stmt_count为会话级限制,但是从下面代码中看到改参数受限于PreparedStmtCount的大小,当PreparedStmtCount超过max_prepared_stmt_count时候就会对当前会话产生报错处理(那么潜在就是会对当前所有会话产生报错处理,因为如果会话级别不设置max_prepared_stmt_count的话所有会话都会遇到该问题),因此文档这里是否说错了(或者文档说的对,代码有BUG)?
问题2:当前参数并未生效,看AddPreparedStmt这个方法中,当newPreparedStmtCount>maxPreparedStmtCount时就会报错,但是实际中newPreparedStmtCount是大于maxPreparedStmtCoun的,假设走了if maxPreparedStmtCount >= 0 && newPreparedStmtCount > maxPreparedStmtCount这个逻辑,那么就应该出现atomic.AddInt64(&PreparedStmtCount, -1),就不应该每次编译新语句的时候在prometheus中看到tidb_prepared_statement_count指标每次都增加的情况,这是哪里理解有问题呢?