oom-use-tmp-storage:哪些算子支持使用临时磁盘空间


oom-use-tmp-storage 说能够支持部分操作在超过mem_quota_query时使用临时磁盘,那么具体有哪些算子或操作从哪个版本开始能够使用临时磁盘空间来避免Oom呢?

等大佬来回答吧,我记得之前分享会的时候有讲过:
即使是使用了 临时磁盘来做数据缓存, 还是会有部分的数据会留存在内中,会有帮助,但是比较有限

上一下版主交流会

$ find . -name '*.go'|xargs grep EnableTmpStorageOnOOM
./config/config.go:	// TempStorageQuota describe the temporary storage Quota during query exector when TiDBEnableTmpStorageOnOOM is enabled
./executor/sort.go:	if variable.EnableTmpStorageOnOOM.Load() {
./executor/aggregate.go:	if e.ctx.GetSessionVars().TrackAggregateMemoryUsage && variable.EnableTmpStorageOnOOM.Load() {
./executor/executor.go:	if variable.EnableTmpStorageOnOOM.Load() && GlobalDiskUsageTracker != nil {
./executor/join.go:	if variable.EnableTmpStorageOnOOM.Load() {
./executor/cte.go:			if val.(bool) && variable.EnableTmpStorageOnOOM.Load() {
./executor/cte.go:	if variable.EnableTmpStorageOnOOM.Load() {
./executor/merge_join.go:		if variable.EnableTmpStorageOnOOM.Load() {
./planner/core/plan_cost.go:	oomUseTmpStorage := variable.EnableTmpStorageOnOOM.Load()
./planner/core/plan_cost.go:	oomUseTmpStorage := variable.EnableTmpStorageOnOOM.Load()
./tidb-server/main.go:	if variable.EnableTmpStorageOnOOM.Load() {
./tidb-server/main.go:	// check capacity and the quota when EnableTmpStorageOnOOM is enabled
./session/bootstrap.go:	importConfigOption(s, "oom-use-tmp-storage", variable.TiDBEnableTmpStorageOnOOM, valStr)
./sessionctx/variable/tidb_vars.go:	// TiDBEnableTmpStorageOnOOM controls whether to enable the temporary storage for some operators
./sessionctx/variable/tidb_vars.go:	TiDBEnableTmpStorageOnOOM = "tidb_enable_tmp_storage_on_oom"
./sessionctx/variable/tidb_vars.go:	DefTiDBEnableTmpStorageOnOOM                   = true
./sessionctx/variable/tidb_vars.go:	EnableTmpStorageOnOOM       = atomic.NewBool(DefTiDBEnableTmpStorageOnOOM)
./sessionctx/variable/sysvar.go:	{Scope: ScopeGlobal, Name: TiDBEnableTmpStorageOnOOM, Value: BoolToOnOff(DefTiDBEnableTmpStorageOnOOM), Type: TypeBool, SetGlobal: func(s *SessionVars, val string) error {
./sessionctx/variable/sysvar.go:		EnableTmpStorageOnOOM.Store(TiDBOptOn(val))
./sessionctx/variable/sysvar.go:		return BoolToOnOff(EnableTmpStorageOnOOM.Load()), nil

grep 了一下代码,大概有以下几个算子是处理了 spill 到磁盘的

  • sort
  • hashjoin
  • hashagg
  • cte
  • mergeJoin

具体的版本… 假设 v6.2 以后吧
我们近期做了大量的工作,来避免 OOM 的问题(进行中),在接下来会发布出去的版本会感受到这些变化。

至于 oom-use-tmp-storage 这个选项,并不是带上它就不会 OOM 了
举个例子,内存快到 OOM 临界点了,然后去落盘,落盘的速度跟不上内存继续申请的速度,然后还是 OOM 了

就内部实现的完善程度看,对 tidb_mem_quota_query 的支持是更好的
oom-use-tmp-storage 只支持了一部分的算子。预期是 tidb_mem_quota_query 一定要将 OOM 拦下来,如果能落盘就落盘,如果不能时要做 kill query 之类的处理,以保护 tidb 进程不要被 OOM Kill。

1 个赞

如何判断这个参数生效了,或者在SQL执行是确实使用了临时空间

如何判断这个参数生效了,或者在SQL执行是确实使用了临时空间

要不把这个值调小,然后执行相应的 query 去观察?

相关的配置设置上之后,观察目录有没有生成临时文件, 来确认是否使用了

引入 oom-use-tmp-storage 的时间点,和各个算子对落盘的支持的时间点,可能还不太一样
所以文档也没有很细化说哪些算子,从哪个版本开始支持了
可以用尽量新的版本测试

落盘行为是不是放到actionMuForSoftLimit,软限制这里比较好呢?目前我看到软限制部分也只有非并发情况下的聚合算子的AggSpillDiskAction行为才会用到。其余的落盘行为全部都是actionMuForHardLimit,这个和PanicOnExceed是一个级别的,所以很多场景下还没来得及落盘就被cancel了。软限制的softScale固定是硬限制的80%,这个如果把落盘放到软限制中并且把这个参数开放给用户自己设置就比较好了。

举个例子,内存快到 OOM 临界点了,然后去落盘,落盘的速度跟不上内存继续申请的速度,然后还是 OOM 了----->想请问下,假设tidb_mem_quota_query 是1G,那么语句使用多少M的内存时就会去考虑是否落盘呢?这个临界点是怎么计算的?

6.3版本,单线程聚合落盘按照语句内存控制的80%,超过则落盘。其它的落盘均需要达到语句控制内存的100%才会落盘。

那是不是存在这样1个可能,语句正在落盘,但是落盘的时候,语句使用的内存继续上涨,最终导致tidb server oom呢?

有这种情况,但是通常情况下不会,落盘的优先级比较高。假设正在落盘如果此时还有数据流转进来则会等待落盘完成,如果落盘已经完成那么就会触发优先级更低的动作比如cancel。容易导致oom的主要场景是在没有被追踪到的场景(假设你设置了oomaction为cancel),比如hashjoin的匹配阶段一行记录匹配右表很多记录,匹配过程中是没有内存追踪的,虽然这种情况比较少(不排除统计信息过旧导致优化器把大表放到右侧)但是遇到有可能会导致oom的。

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