tidb抽数据oom的问题

为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。

  • 【TiDB 版本】:v4.0.5
  • 【问题描述】:

sqoop 将tidb的数据拖到hive做T+1快照库,TIDB组件总是OOM,内存控制不住,想知道怎么调整

可能是抽取数据量太大了,分批抽取吧。另外你可以看看 SQL 有没有优化办法。

原来这个库,我们使用mysql的

建议你试试上面同事提供的方式 分批抽取看看效果

4.0.6版本,内存就能压得住;感觉是4.0.5和4.0.6内存管理上有区别

可以复现 OOM 的问题吗? 麻烦抓取火焰图我们看看,多谢。

curl -G “ip:port/debug/pprof/heap?seconds=30” > heap.profile

ip地址为tidb服务器的ip,端口为tidb_status_port的端口

一开启任务,瞬间就崩了,然后自动重启,等任务重试的时候,并发低了,就不崩了;任务还在继续跑,现在这个heap文件是抽数据过程中的heap (82.4 KB) ,等下午,我重新跑一遍,尽可能抓住现场

补充,这是4.0.6版本,比4.0.5版本稳定很多,4.0.5导数据是稳定炸,4.0.6版本,就任务启动的时候炸,后面就稳定了

抽数据蹦的前几秒:
Showing nodes accounting for 25617.97MB, 97.60% of 26247.49MB total
Dropped 357 nodes (cum <= 131.24MB)
Showing top 10 nodes out of 18
flat flat% sum% cum cum%
25457.96MB 96.99% 96.99% 25457.96MB 96.99% bytes.makeSlice
85.01MB 0.32% 97.32% 25542.97MB 97.32% bytes.(*Buffer).grow
74.50MB 0.28% 97.60% 217.01MB 0.83% github.com/pingcap/tidb/types.Time.DateFormat
0.50MB 0.0019% 97.60% 178.98MB 0.68% github.com/pingcap/tidb/store/tikv.(*copIteratorWorker).handleCopStreamResult
0 0% 97.60% 25457.96MB 96.99% bytes.(*Buffer).Write
0 0% 97.60% 304.95MB 1.16% github.com/pingcap/tidb/server.(*Server).onConn
0 0% 97.60% 301.92MB 1.15% github.com/pingcap/tidb/server.(*clientConn).Run
0 0% 97.60% 301.92MB 1.15% github.com/pingcap/tidb/server.(*clientConn).dispatch
0 0% 97.60% 301.92MB 1.15% github.com/pingcap/tidb/server.(*clientConn).handleQuery
0 0% 97.60% 294.92MB 1.12% github.com/pingcap/tidb/server.(*clientConn).writeChunks

看起来是抽取数据量较大导致 oom,建议减少并发。

对于 TiDB,可以考虑降低读取任务并发度,如调低

tidb_distsql_scan_concurrency

参数减少内存使用,但可能会增加执行时间。

另外,可以考虑通过查询

select * from information_schema.processlist order by MEM;

来观察当前 SQL 内存使用情况

看processlist中的mem,都是MB级别的,不太像是这个导致的oom;看pprof中的heap,99.x%都是在makeSlice里面,应该是传输数据buffer吧?这块请问怎么限制?(我不懂这个,可否根据游标,发送多少,取多少,而不是一次性全部从tikv中load出来,全塞到tidb的buffer中,,,我瞎说的)

可否根据游标,发送多少,取多少,而不是一次性全部从tikv中load出来,全塞到tidb的buffer中,,,我瞎说的

目前是这样的逻辑,且会进行一些内存复用。

这里 heap 使用高有两种可能,一种是确实并发比较多且读的数据多,导致内存分配较多,这种情况可以降低 client 并发数,同时调整上面提到的 TiDB distsql 参数看看情况。

也可以尝试调小 tidb_mem_quota_query 来限制单个 query 的内存使用,在超出 query 内存限制的情况下报错,把消耗较多内存的 SQL 暴露出来然后再分析。

tidb_mem_quota_query限制sql的内存跟,processlist中的mem的指标是一个吗?如果是一个,经观察,抽数据用的sql对应的sql的mem并不大,MB级别

tidb_mem_quota_query这个参数比较那啥,做不到限制:

  • 假如跟processlist中mem是一个指标,那并不会超过;日志中看到expensivesql,基本都是超过60s执行时间的,并不是oom相关
  • 假若不是一个指标,那么按照文档,有两个操作: 1. log(没看到) 2. cancel(那岂不是永远失败),我本以为tidb_mem_quota_query能限制,已经设置为1G,单实际上,还是oom;是系统级别的oom

是一个指标。目前是说已经调小了 tidb_mem_quota_query 为 1GB 在抽取数据过程中,没有 query oom log 和报错,但 tidb-server 仍然会 oom 对么? 如果是这样可能需要针对 workload 具体分析一下,看看是否有可能 ref 内存没有释放。

另外可以尝试通过根据 SQL 使用算子调整减小并发度控制内存,

Table/Index Scan 相关参数
tidb_index_lookup_size
tidb_index_lookup_concurrency
tidb_index_serial_scan_concurrency
tidb_distsql_scan_concurrency

join/agg/projection 算子相关参数
tidb_index_join_batch_size
tidb_index_lookup_join_concurrency
tidb_hash_join_concurrency
tidb_projection_concurrency
tidb_hashagg_partial_concurrency
tidb_hashagg_final_concurrency

目前该集群为调研目的,仅包含按id范围抽数据,这个该怎么看呢

可以 explain 看下 SQL 语句执行方式。
例如如果只包含 table scan 或者 index scan 操作,可以把上面 table/index scan 相对应参数设置为 1 降低并发度,可以并发数据量但会增加时延。
如果包含 join 和聚合 等算子,可以一起调整下列的参数降低计算并发度。

好哒,目前6个TIDB实例节点,配置为16核心128G,没问题;峰值使用114G内存,继续测试中,还没有OOM过呢,甚是欢喜。

1 Like

:+1: