单次查询表数据太大超过1G触发了oom

我不想修改mem-quota-query参数,我可以通过使用 Cursor Fetch,设置FetchSize的方式解决吗?

好像不行,举个栗子,你要的数据分散在各个 tikv 节点上,需要拿回 到 tidb 节点上聚合之后,才能 limit,因为会有排序或者分组之类的一些条件,必须数据在一起之后才会有效…

有效的办法:

  1. 增大 tidb 节点的内存
  2. 查询数据时,减少聚合大小,尽量使用下推计算…

OOM并不是前端堵塞,是tidb缓存tikv的数据以及做算子运算时开了并发缓存了较多数据导致。尝试调整 tidb_distsql_scan_concurrency减少一些会减少oom的问题,你可以设置为2试试。

你的cursor fetch已是在tidb server层了,mem-quota-query设置就在tidb server层,所以不能

贴下版本 SQL explain执行计划看看

为什么不想修改mem-quota-query参数?要么优化语句,要么提高阈值

Cursor Fetch的方式不是分批去拉去数据吗?我现在的查询很简单,就是datax同步数据,但是数据太多了,然后datax没法手动去控制分批

我觉得用Cursor Fetch去流式读取的时候结果集是已经全部在tidb server中了的,并不是说他能改变你的SQL实现limit offset那种效果。
所以解决办法就是上面kongdom说的,要么优化SQL,要么提高mem quota的阈值

不能,原因我说的狠清楚了,解决方式也给了,你可以参考下

这句是不对的,缓存在server端的结果就是一个resultSet是一个chunk,读取完后继续取。缓存是一个max_chunk_size=1024行的结果集。

加大服务器内存就好了 1g内存很常见

分批查询?比如指定id

tidb server 从tikv 上获取数据确实是一个一个chunk 流式获取,但是有个疑问,如果是select xxx from xx limit n;这种语句,应该是需要把tikv获取到的数据放到tidb server 里面的内存种排序吧(假设是全部扫描没有利用到索引的这种执行计划),这种情况下,tidb server 应该是比较容易oom吧

这个没有涉及到排序,如果limit n,这个n值比较小则封装的task数较少大概率小于tidb_distsql_scan_concurrency则不容易oom,最大也是tidb_distsql_scan_concurrency=15(默认值),也就是最多使用内存15region_size,当然这种情况非常少,因为一个region中记录数太多了,你需要limit 几十万或者上百万才可能用到15个region,因此只是limit n情况几乎不需要考虑oom的问题。
你可能想要表达的是select xxx from xx order by cola limit n,cola不是索引列这种情况吧?首先这种情况下cop_task个数基本上是该表所有region数,但是针对每一个cop_task会将topN算子下推到tikv上执行,也就是针对每一个cop_task(这里基本上等同于region)均获取topN值,然后并发的返回tidb-server,那么tidb-server中最多缓存limit N * tidb_distsql_scan_concurrency记录数,所以这里会发生oom的概率很小。
进一步分析,假设你需要的是select cola ,count(
) from xx group by cola limit n; cola上并没有索引的情况下,是否会发生oom呢?这种涉及到聚合运算的如果数据离散度较低(重复度)一般情况下会在tikv层做hashagg聚合然后将数据拿到tidb层进行二次聚合运算发生oom的概率较小,如果数据离散度较高,大量数据放到tidb层做hashagg运算,那么默认配置下会有较大概率发生oom。
大数据量在tidb-server层如何控制其避免oom呢?首先要打开落盘相关参数,让一些算子能够进行落盘,但是hashagg在并发情况下并不能落盘,需要将tidb_hashagg_partial_concurrency,tidb_hashagg_final_concurrency均设置为1才能进行落盘,但是没有并发加持加之写入磁盘,效率会比较慢,但是避免了oom(这里只是理论上会避免oom,tidb的内存追踪评估在准确度上要进一步加强才能够完全避免oom)。

1 个赞

tidb,tikv对于task的请求属于生产者消费者模式。tidb是消费者,tikv是生产者。当tidb消费的慢(客户端获取数据慢)的时候那么会容易在tidb端的缓冲区积压导致tidb容易oom,当tidb消费的快,但是grpc网络慢的时候理论上容易在tikv端形成积压导致tikv容易oom。对于单表全表查询,当tidb客户端获取数据很快时候一般不会太大问题。还有两个地方需要注意:1、region的分裂,如果region分裂不及时导致region很大,那么可能会导致oom,所以region过大后分裂很重要;2、tidb_enable_rate_limit_action这个参数控制当cop_tak并发请求队列缓存数据过大时导致内存上线超过当前session的内存使用量后会优先触发流控,每执行完一次cop_task则判断一次,如果内存使用超过tidb_mem_quota_query那么当前并发数-1,这里会带来一个潜在问题,也就是流控的优先级高于cancel的优先级,导致最后无法流控后才会被杀掉,看到的现象就是内存超过很多了还没有被杀掉,这个情况下当并发session多可能导致tidb-server整体oom,因此建议将tidb_enable_rate_limit_action设置为OFF,来让cancel动作更及时。

1 个赞

这个是tidb无法缓存内容了 取的太多了