Out Of Memory Quota!

JDBC 定时增量读取大表的时候,报错Caused by: java.sql.SQLException: Out Of Memory Quota![conn_id=22927] ,推测是TIDB Server端内存不足;

1、无法修改源码
2、无法修改SQL使用order by limit减少每个批次的数据量;
3、通过jdbc连接参数,可以避免这个问题吗?(尝试过useCursorFetch=true&fetch.size=1000 好像没法避免)

  • 你之前useCursorFetch方案无效是 v6.5.x 版本机制问题,游标模式预加载全量数据集到服务端内存;
  • 仅依靠 JDBC 连接参数可以实现流式读取,核心配置 defaultFetchSize=-2147483648 + 懒加载游标;
  • 搭配会话变量tidb_mem_quota_oom_action=spill实现内存超限自动落盘,彻底解决定时增量读取大表触发内存配额报错。

这是 TiDB 侧 tidb_mem_quota_query 触发,单连接仍可能物化大结果。JDBC fetch size 往往挡不住服务端算子内存。可调大该会话/全局 mem quota,或换流式读取协议;根治仍是缩小单次扫描范围。仅改 JDBC 参数通常不够。

Out Of Memory Quota 是 TiDB Server 侧 mem-quota-query(或会话 tidb_mem_quota_query)超限,JDBC 的 useCursorFetch/fetchSize 主要约束客户端取行节奏,不能替代服务端执行期内存上限。

建议:
1)会话级临时放大:SET SESSION tidb_mem_quota_query = 10737418240;(按机器余量调,单位字节)
2)全局看 config 的 mem-quota-query,并配合 OOMAction(log/cancel)观察慢查询/Dashboard
3)增量读尽量用主键/唯一键范围谓词分批(WHERE id > ? AND id <= ?),比单纯 JDBC 参数更有效
4)排查执行计划是否有大 Sort/HashJoin/HashAgg;能走索引点查/范围扫就避免全表物化

仅改 JDBC URL 通常绕不过该报错。

1 个赞

总结很详细,仅改 JDBC URL 确实不行

JDBC URL 中添加:&sessionVariables=tidb_mem_quota_query=4294967296 是否可以?

这个报错是TiDB Server端内存超限,不是JDBC客户端的问题。你试过useCursorFetch但没用,因为TiDB的cursor模式本身也会占用内存。

既然不能改SQL,建议从这几个方向处理:

  1. 调大TiDB实例的mem-quota-query参数,默认1GB,可以临时调到2-4GB试试:
    set global mem-quota-query = 4294967296;

  2. 检查TiDB日志确认是哪个query触发的,用慢日志定位具体内存消耗点。

总结的很详细,只改 JDBC URL 确实不行

该报错表示单条 SQL 达到 tidb_mem_quota_query,不等于 TiDB 进程物理内存耗尽。useCursorFetch=true 配合正数 fetchSize 仍可能在 TiDB 端缓存结果;可优先测试 setFetchSize(Integer.MIN_VALUE)。v8.3.0 以上如使用 Cursor Fetch,可测试 tidb_enable_lazy_cursor_fetch=ON,但受执行计划和事务限制。建议楼主补充 TiDB/Connector-J 版本、完整 SQL、EXPLAIN、内存额度及并发数。不要直接全局调大配额,并发会叠加内存风险;算子落盘也会增加磁盘 IO。

tidb_mem_quota_query 默认1G,我改成32G了

感觉可以从连接层的流式读取/Fetch策略去排查,TiDB 物理内存或 SQL 本身应该问题。

查看下游标抓取是否未生效?TiDB 侧读取内存超限?JDBC 参数无法规避服务端内存压力。

问题解决了吗楼主

如果无法修改代码,可试试在 JDBC 实现流式读取