analyze table 代码调用OOM,终端执行没问题

【 TiDB 使用环境】生产环境
【 TiDB 版本】v6.5.1
【复现路径】执行 analyze table db_name.table_name
【遇到的问题:】

SQLSTATE[HY000]: General error: 1105 Out Of Memory Quota![conn_id=2826202280314578355]%!(EXTRA *errors.fundamental=analyze panic due to memory quota exceeds, please try with smaller samplerate(refer to 110000/count))

用代码调用执行 analyze table db_name.table_name 某些时候会出现上面的报错,但是到mysql终端手动执行就不报错。

看下全局变量 tidb_analyze_version ,如果是2考虑调整为1试试

或者你就是放大单sql的内存使用限制 tidb_mem_quota_query

问题是两种执行方式不一样,终端执行没有问题,代码执行有问题。

可能的原因
表数据量大:TiDB 在执行 ANALYZE TABLE 时需要扫描整个表的数据,并计算统计信息,这可能会导致内存使用过高。
TiDB 版本问题:版本可能存在bug。

我的tidb_mem_quota_query是2G,难道只限制了代码调用,而终端执行不限制所以不报错?

可能的原因和解决方案:

  1. 内存配额限制

TiDB有一个系统变量tidb_mem_quota_analyze用于控制ANALYZE语句的内存使用1。当通过代码执行时,可能没有正确设置这个变量,导致内存使用超出了默认限制。

  1. 采样率问题

错误信息中提到了"please try with smaller samplerate",这表明当前的采样率可能过高,导致内存使用过大2。

  1. 并发执行

通过代码执行时,可能同时触发了多个ANALYZE操作,累积的内存使用超过了单个操作的限制3。

  1. 表大小和复杂性

如果表非常大或结构复杂,可能需要更多的内存来完成统计信息的收集4。

  1. 系统负载

在高负载情况下,系统可用内存可能较少,更容易触发OOM错误5。

解决方案:

  1. 调整内存配额:可以尝试增加tidb_mem_quota_analyze的值:
SET GLOBAL tidb_mem_quota_analyze = 8589934592; -- 设置为8GB
  1. 降低采样率:使用较小的采样率来减少内存使用:
ANALYZE TABLE db_name.table_name WITH 10 BUCKETS, SAMPLERATE 0.1;
  1. 控制并发:确保代码中不会同时触发多个ANALYZE操作。可以使用队列或锁来控制并发。
  2. 分批处理:对于大表,可以考虑只对部分列进行分析,或者使用增量分析:
ANALYZE INCREMENTAL TABLE db_name.table_name INDEX idx_name;
  1. 监控系统资源:使用TiDB的监控工具(如Grafana面板)来监控系统资源使用情况,选择在系统负载较低时执行ANALYZE 6。
  2. 使用异步分析:TiDB支持异步执行ANALYZE,这可以减少对在线业务的影响:
SET tidb_enable_fast_analyze = 1;
ANALYZE TABLE db_name.table_name;
  1. 检查TiDB配置:确保TiDB的内存相关配置合理,例如server-memory-quotamemory-usage-alarm-ratio 7。

示例SQL:

以下是一个综合示例,展示了如何安全地执行ANALYZE:

-- 设置全局内存配额(需要有SUPER权限)
SET GLOBAL tidb_mem_quota_analyze = 8589934592;

-- 在会话中启用快速分析
SET SESSION tidb_enable_fast_analyze = 1;

-- 使用较低的采样率执行ANALYZE
ANALYZE TABLE db_name.table_name WITH 10 BUCKETS, SAMPLERATE 0.1;

-- 如果是大表,考虑使用增量分析
ANALYZE INCREMENTAL TABLE db_name.table_name INDEX idx_name;

-- 检查分析结果
SHOW STATS_META WHERE db_name = 'your_db_name' AND table_name = 'your_table_name';

通过实施这些措施,您应该能够解决代码执行ANALYZE TABLE时遇到的OOM问题。如果问题仍然存在,建议收集详细的执行日志和监控数据

tidb_enable_fast_analyze 这个不建议用吧

我想到一个方案,就是在代码里面调用mysql终端命令,而不是mysql-sdk方法

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