tidb集群,单个sql会话查询超过参数限制,仍能查询

【 TiDB 使用环境】生产环境
【 TiDB 版本】v6.5.0
【复现路径】做过哪些操作出现的问题
【遇到的问题:问题现象及影响】
生环境tidb集群中的Tidb-server的参数配置:
mem-quota-query: 16g
performance.txn-total-size-limit: 4g

但是,出现一种情况,用户发起一个大的sql查询,消耗内存高达60g+

正常情况下,超过16g,tidb-server应该主动中断这个用户的连接查询,但是,从上面的截图来看,是一直没有释放,最后导致OOM。

【资源配置】
【附件:截图/日志/监控】

当单个 SQL 会话的内存使用量超过 mem-quota-query 参数设置的值时,TiDB 会主动中断该会话。但是,您提供的截图显示,该会话一直没有被释放,最终导致了 OOM。

这种情况可能是由于 TiDB 的参数设置不合理导致的。您可以尝试调整 mem-quota-query 参数的值,以确保单个 SQL 会话的内存使用量不会超过 TiDB 的内存限制。另外,您还可以尝试调整 performance.txn-total-size-limit 参数的值,以确保 TiDB 的事务内存使用量不会超过 TiDB 的内存限制。

如果您已经尝试了上述方法,但仍然遇到了问题,您可以考虑使用 TiDB 的 Profile 功能来分析该 SQL 会话的性能瓶颈。Profile 功能可以帮助您分析 SQL 语句的执行计划、瓶颈和资源消耗情况,从而帮助您优化 SQL 语句的性能。

1 个赞


会不会跟这几个参数有关系呢?

首先你按表妹说的意思看下那查询限制参数设置值是否过大,大到已发超出tidb实例允许的值就没有意义了,那样的话根没设置没什么区别。

其次,你自己的回复中提到的,我觉得也是有可能的,你都有生产环境了,肯定有测试环境,在测试环境试下:
单独的tidb_mem_quota_query
及同时与tmp相关的参数组合使用下的测试。
等着围观你的测试哟。

再次,我想说,如果上边两种都排查了,是不是当前版本的资源设置有缺陷?
我看到v7版本的tidb在资源控制方面加强了很多,号称里程碑:v7-基于资源组的资源管控特性
对 TiDB 具有里程碑的意义-多租户基础
三种方式绑定到资源组:通过 CREATE USER 或 ALTER USER 语句将用户绑定到特定的资源组,使得用户会话始终受到设定边界约束;
通过 SET RESOURCE GROUP 设置当前会话的资源组;
通过 Hint RESOURCE_GROUP() 设置当前语句的资源组。

1 个赞

在 v6.5.0 之前的版本中,该变量用来设置单条查询的内存使用限制。

在 v6.5.0 及之后的版本中,该变量用来设置单个会话整体的内存使用限制,如果某个会话执行过程中使用的内存量超过该阈值,会触发系统变量 tidb_mem_oom_action 中指定的行为。

你设置了tidb_mem_oom_action`没?
如果变量值为 LOG,那么当一条 SQL 的内存使用超过一定阈值(由 session 变量 tidb_mem_quota_query 控制)后,这条 SQL 会继续执行,但 TiDB 会在 log 文件中打印一条 LOG。

1 个赞

tidb_enable_rate_limit_action

注意

该变量默认开启,但可能导致内存不受 tidb_mem_quota_query 控制,从而加剧 OOM 风险,因此建议将该变量值调整为 OFF

  • 作用域:SESSION | GLOBAL
  • 默认值:ON
  • 这个变量控制是否为读数据的算子开启动态内存控制功能。读数据的算子默认启用 tidb_distsql_scan_concurrency 所允许的最大线程数来读取数据。当单条 SQL 语句的内存使用每超过 tidb_mem_quota_query 一次,读数据的算子会停止一个线程。
  • 当读数据的算子只剩 1 个线程且当单条 SQL 语句的内存使用继续超过 tidb_mem_quota_query 时,该 SQL 语句会触发其它的内存控制行为,例如落盘
1 个赞

这个参数检查下,最近我们碰到过这种问题,工单告诉我们是这个参数导致的

1 个赞

直接脚本干,简单命令,从内存和time 两个维度,而且还有记录慢SQL,方便可查

for list in /mysql5.7/bin/mysql -hyourip -p'yourpassword' -vvv -e " select id from INFORMATION_SCHEMA.processlist a where a.info is not null and (mem >=11474836480 or time >600);" |grep -Ev 'id|ID|iD|Id' |awk -F "|" '{print $2}'
do
echo $list
/mysql5.7/bin/mysql -hyourip -p’yourpassword’ -vvv -e “select id,time,info,mem from INFORMATION_SCHEMA.processlist a where id=$list and a.info is not null;;” >/killsqllog/date +%s.log
/mysql5.7/bin/mysql -hyourip -p’yourpassword’ -vvv -e " kill tidb $list ;"
done;

1 个赞

tidb互助群里,有大佬指点,已经找到问题原因。

确实是因为tidb_mem_oom_action参数设置的问题,此变量参数,只支持在系统参数命令行调整生效,不支持修改配置文件生效。

修改方法如下:

mysql> set global  tidb_mem_oom_action='cancel';
Query OK, 0 rows affected (0.02 sec)

mysql> show variables like '%oom%';
+--------------------------------+--------+
| Variable_name                  | Value  |
+--------------------------------+--------+
| tidb_enable_tmp_storage_on_oom | ON     |
| tidb_mem_oom_action            | CANCEL |
+--------------------------------+--------+
2 rows in set (0.01 sec)

然后,再使用大SQL进行查询,超过mem-quota-query,就会抛出OOM。

此话题已在最后回复的 60 天后被自动关闭。不再允许新回复。