【Bug】tiflash 内存超限,Tiflash如何分配查询内存的?

【 TiDB 使用环境】生产环境
【 TiDB 版本】7.1.0

【背景】
1、查询所需内存 231.12 GiB > max_memory_usage_for_all_queries 总内存*0.9( 226.57G)
2、任务串行执行,单条sql内存用量大概100G左右(上下浮动10G)

【问题】
Tiflash如何分配内存的?
通过错误日志排查发现,应该是前置分配内存

【现象】
1、相似的两个TiFlash查询A、查询B,这俩任务串行执行。
2、A查询执行完成后,开始B查询,此时有开始C查询(内存占用极小),此时B和C查询同时失败

B查询失败:

[mpp-version=1] [error="other error for mpp stream: From MPP<query:<query_ts:1728504882699720307, local_query_id:1399727, server_id:1124321, start_ts:453117183961071674>,task_id:2>: Code: 0, e.displayText() = DB::TiFlashException: Memory limit (total) exceeded caused by 'out of memory quota for data computing' : would use 231.12 GiB for data computing (attempt to allocate chunk of 16 bytes), limit of memory for data computing: 226.57 GiB, e.what() = DB::TiFlashException,"]

C查询失败:

 [txn_mode=PESSIMISTIC] [timestamp=453117183961071674] [err="other
error for mpp stream: From MPP<query:<query_ts:1728504882699720307, local_query_id:13
99727, server_id:1124321, start_ts:453117183961071674>,task_id:2>: Code: 0, e.display
Text() = DB::TiFlashException: Memory limit (total) exceeded caused by 'out of memory
 quota for data computing' : would use 231.12 GiB for data computing (attempt to allo
cate chunk of 16 bytes), limit of memory for data computing: 226.57 GiB,

B 查询在执行过程中占用了大量内存,而系统可用内存不足以支持 C 查询,即使 C 的内存占用很小,也可能导致内存分配失败。
TiFlash 通过 max_memory_usage_for_all_queries 参数限制查询的内存使用量。如果 B 查询的内存使用超过了这个限制,C 查询可能因为无法获得足够的内存资源而失败,即使 C 的内存占用很小,也可能导致查询失败。

优化建议,可以尝试以下方法:

1、优化B查询,减少内存使用量;
2、增加机器内存,或者扩容tiflash节点;
3、可以设置tiflash_mem_quota_query_per_node参数,限制单个查询在单个 TiFlash 节点上的内存使用上限,超过该限制时 TiFlash 会报错并终止该查询。

全局背景下是A执行完,执行B和C 的查询全部失败。

A执行成功,说明A用的内存没有超过内存限制;
A执行完成后,内存就会释放;
B执行时报错,是因为超过了内存限制

A和B单独查询都可以成功。

执行完,内存不会立即释放吧?

单独执行下A,观察grafana上tiflash的内存使用情况,观察A执行完成后tiflash释放内存的时间

可以考虑使用算子落盘来解决一下这个问题。

https://docs.pingcap.com/zh/tidb/stable/tiflash-spill-disk

另外你提到的这个 max_memory_usage_for_all_queries参数没有在文档中找到。可能是个无效的参数。所以当内存没法得到有效的控制。

考虑将 max_memory_usage_for_all_queries 的值适当提高,或者优化查询以减少内存使用。

1 个赞

当前已经是0.9

测试A、B两个查询间隔10s,内存释放较为理想
![企业微信截图_bc120c15-c63a-4b5a-b561-ae4648a25feb|690x475]

1 个赞

1、我这边调研下
2、max_memory_usage_for_all_queries 在tiflash配置文件中有https://docs.pingcap.com/zh/tidb/stable/tiflash-configuration

1 个赞

那间隔10s,B查询就不会报错了吧

是的,
不过部分场景无法加间隔,最终还是优化sql或者调整系统其它参数。

没法加间隔的,就需要加内存或者增加tiflash节点;
再就是优化sql

我的理解有问题。我还以为真的是tiflash oom了。其实这个报错就是max_memory_usage_for_all_queries参数设置后的效果。上面这个issue是类似的问题。
得到的回复是

As discussed offline, the oom is expected because the default value of max_memory_usage_for_all_queries is changed.

另外就是你感觉其中一个sql已经运行完了。内存应该释放了,但实际好像还是统计进去了。这个问题,建议还是去github提个issue看看。起码现在从你后面提供的这个监控图上看,似乎是没有到230g这么高的。bug的概率还是不低的。

从TiFlash v7.4.0开始,引入了资源管控功能,可以通过设置enable_resource_control = true 来开启,这有助于更好地管理资源使用。

1 个赞

收到,稍后整到GitHub去
https://github.com/pingcap/tidb/issues/56669

1 个赞

感觉你当前也只能,岔开时间跑吧。

当然用 ru 可以试试。

看下SQL是否可以优化,或者错开时间窗口去执行