tidb参数变量max_prepared_stmt_count不生效

【 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指标每次都增加的情况,这是哪里理解有问题呢?

这是一个 bug,已提 issue https://github.com/pingcap/tidb/issues/39735