Skip to content
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c4f2c5e
Document global memory management framework in TiDB
solotzg Sep 24, 2025
80a85a0
Document new TiDB memory management system variables
solotzg Sep 24, 2025
9fc3a44
Revise TiDB global memory management documentation
solotzg Sep 25, 2025
3642a34
Update system-variables.md
solotzg Sep 25, 2025
8d9e47e
Update memory management mode descriptions in docs
solotzg Sep 25, 2025
eca03a5
Fix formatting and links in memory usage documentation
solotzg Sep 25, 2025
3b590b5
Fix formatting and clarify SQL memory arbitration
solotzg Sep 25, 2025
9c6b567
Fix formatting and indentation in system-variables.md
solotzg Sep 25, 2025
c942739
Apply suggestions from code review
hfxsd Oct 11, 2025
bba68ad
Update memory management configuration details
solotzg Oct 30, 2025
0e1acc9
Clarify behavior of memory management variable
solotzg Nov 6, 2025
3790a3d
Enhance documentation on memory arbitrator modes
solotzg Nov 6, 2025
4925ef3
Update system-variables.md
solotzg Nov 11, 2025
aab9355
Update system-variables.md
solotzg Nov 11, 2025
d81575c
Update system-variables.md
solotzg Nov 11, 2025
0811e29
Update system-variables.md
solotzg Nov 11, 2025
f953fab
Update memory arbitration modes in documentation
solotzg Nov 12, 2025
c896061
exchange parts
solotzg Nov 14, 2025
ad41b85
Enhance documentation on TiDB memory management
solotzg Nov 17, 2025
7e84d1c
Fix formatting and clarify memory arbitration modes
solotzg Nov 17, 2025
f4fbe98
Update memory management descriptions in documentation
solotzg Nov 17, 2025
da94f14
Update memory arbitration mode documentation
solotzg Nov 17, 2025
6b348b2
Fix links and descriptions for memory management variables
solotzg Nov 17, 2025
e5280b6
Updated the memory arbitration mode section
solotzg Nov 20, 2025
f5850ed
Update memory arbitration mode documentation
solotzg Nov 24, 2025
2dc5e31
Fix typo in memory arbitration section
solotzg Nov 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 115 additions & 2 deletions configure-memory-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,6 @@ TiDB 支持对执行算子的数据落盘功能。当 SQL 的内存使用超过
9 rows in set (1 min 37.428 sec)
```

## 其它

### 设置环境变量 `GOMEMLIMIT` 缓解 OOM 问题

Golang 自 Go 1.19 版本开始引入 [`GOMEMLIMIT`](https://pkg.go.dev/[email protected]#hdr-Environment_Variables) 环境变量,该变量用来设置触发 Go GC 的内存上限。
Expand All @@ -231,3 +229,118 @@ Golang 自 Go 1.19 版本开始引入 [`GOMEMLIMIT`](https://pkg.go.dev/runtime@
- 在 TiDB v6.1.3 下,设置 `GOMEMLIMIT` 为 40000 MiB,模拟负载长期稳定运行、TiDB server 未发生 OOM 且进程最高内存用量稳定在 40.8 GiB 左右:

![v6.1.3 workload no oom with GOMEMLIMIT](/media/configure-memory-usage-613-no-oom.png)

## 内存仲裁模式

TiDB 从 v9.0.0 开始引入新的内存管理机制,可通过系统变量 [`tidb_mem_arbitrator_mode`](/system-variables.md#tidb_mem_arbitrator_mode-从-v900-版本开始引入) 或 TiDB 配置文件参数 `instance.tidb_mem_arbitrator_mode` 开启。

`tidb_mem_arbitrator_mode` 默认为 `disable`,表示禁用内存仲裁模式,保持内存资源先使用后上报的机制以及相关 [内存控制行为](#如何配置-tidb-server-实例使用内存的阈值)。

设置 `tidb_mem_arbitrator_mode` 为 `standard` 或 `priority` 表示启用内存仲裁模式。内存资源的使用按照先订阅后分配的机制,由各个 TiDB 实例中唯一的仲裁者统筹。预期 TiDB 实例的整体内存使用量不会超过 `tidb_server_memory_limit` 的限制,且 [内存占用过高时的报警](#tidb-server-内存占用过高时的报警) 将不再生效。

仲裁者可通过终止 SQL 来回收内存资源(不可终止 `DDL`|`DCL`|`TCL` 类型 SQL),并向客户端返回编号为 `8180` 的错误。错误格式为:`Query execution was stopped by the global memory arbitrator [reason=?, path=?] [conn=?]`:

- `conn`:连接(会话)ID
- `reason`:终止 SQL 的具体原因
- `path`:SQL 被终止的阶段
- 无 `path` 字段则默认为执行阶段
- `ParseSQL`(解析)
- `CompilePlan`(编译执行计划)

### `standard` 模式

SQL 运行过程中会动态地向仲裁者订阅内存资源并阻塞式等待,仲裁者按先来先服务原则处理订阅请求

- 解析 SQL 或编译执行计划时,需要订阅的内存份额由 TiDB 估算,与 SQL 关键字数量成正比
- 如果全局内存资源不足,仲裁者令请求失败并终止 SQL,返回错误中 `reason` 字段为 `CANCEL(out-of-quota & standard-mode)`

### `priority` 模式

SQL 运行过程中会动态地向仲裁者订阅内存资源并阻塞式等待,仲裁者根据 SQL 的 [资源组优先级](/information-schema/information-schema-resource-groups.md) (`LOW | MEDIUM | HIGH`) 处理订阅请求

- 解析 SQL 或编译执行计划时,需要订阅的内存份额由 TiDB 估算,与 SQL 关键字数量成正比
- 不同于 `standard` 模式,`priority` 模式下除非面临内存溢出 (OOM) 风险,否则订阅失败后不会立刻终止 SQL
- 所有订阅请求按照优先级从高到低排队等待资源,同级别请求按照发起顺序排序
- 全局内存资源不足时
- 仲裁者按顺序(优先级从低到高,内存使用量从大到小)终止低优先级 SQL,回收资源来满足高优先级 SQL
- 返回错误中 `reason` 字段为 `CANCEL(out-of-quota & priority-mode)`
- 没有可终止的 SQL,则等待现有 SQL 执行完后释放资源

如果要让 SQL 避免等待内存资源所造成的延迟开销,可以设置 session 变量 [`tidb_mem_arbitrator_wait_averse`](/system-variables.md#tidb_mem_arbitrator_wait_averse-从-v900-版本开始引入) 为 `1`

- 相关 SQL 的订阅请求自动绑定优先级 `HIGH`
- 全局内存资源不足时仲裁者直接终止相关 SQL,返回错误中 `reason` 字段为 `CANCEL(out-of-quota & wait-averse)`

### 内存风险控制

当 TiDB 实例的内存用量达到 [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-从-v640-版本开始引入) 的 95% 这一阈值时,仲裁者开始处理内存风险。如果面临 `OOM` 风险(内存用量短期无法降低到安全线或者全局内存使用速率过小),仲裁者会按顺序(优先级从低到高,内存使用量从大到小)强制终止 SQL,返回错误中 `reason` 字段为 `KILL(out-of-memory)`。

如果需要在内存资源不足时强制运行 SQL,可以设置 session 变量 [`tidb_mem_arbitrator_wait_averse`](/system-variables.md#tidb_mem_arbitrator_wait_averse-从-v900-版本开始引入) 为 `nolimit`。该参数令相关 SQL 使用内存不受限制,但可能导致 TiDB 实例 `OOM`。

### 手动保障内存安全

通过系统变量 [`tidb_mem_arbitrator_soft_limit`](/system-variables.md#tidb_mem_arbitrator_soft_limit-从-v900-版本开始引入) 或 TiDB 配置文件参数 `instance.tidb_mem_arbitrator_soft_limit` 可以设置 TiDB 实例的内存资源份额上限。上限越小,全局内存越安全,但内存资源利用率越低。该变量可用于手动快速收敛内存风险。

TiDB 内部会缓存部分 SQL 的历史最大内存资源用量,并在 SQL 下次执行前预先订阅足量内存资源份额。如果已知 SQL 存在大量内存使用不受控制的问题,可通过 session 变量 [`tidb_mem_arbitrator_query_reserved`](/system-variables.md#tidb_mem_arbitrator_query_reserved-从-v900-版本开始引入) 指定 SQL 订阅的份额。该值越大,全局内存越安全,但内存资源利用率越低。预先订阅足量或超量的份额可以有效地保障 SQL 的内存资源隔离性。

### 监控和观测指标

`Grafana` 监控新增 `TiDB / Memory Arbitrator` 面板,包含以下指标:

- Work Mode:各个 TiDB 实例的内存管理模式
- Arbitration Exec:仲裁处理各类请求的统计
- Events:仲裁模式内各类事件的统计
- Mem Quota Stats:各类内存资源份额占用
- Mem Quota Arbitration:内存资源订阅请求处理耗时
- Mem Pool Stats:各类内存池的数量
- Runtime Mem Pressure:内存压力值(实际内存使用和内存资源份额使用的比率)
- Waiting Tasks:排队等待中的各类任务数量

[`SLOW_QUERY`](/information-schema/information-schema-slow-query.md) 新增 `Mem_arbitration` 字段表示 SQL 等待内存资源的总耗时。[TiDB Dashboard 慢查询页面](/dashboard/dashboard-slow-query.md) 中的 `Mem Arbitration` 列也会显示该信息。

[`PROCESSLIST`](/information-schema/information-schema-processlist.md) 新增以下字段:

- `MEM_ARBITRATION`:目前为止 SQL 等待内存资源的总耗时
- `MEM_WAIT_ARBITRATE_START`:当前内存资源订阅请求的开始时间(没有则为 NULL)
- `MEM_WAIT_ARBITRATE_BYTES`:当前内存资源订阅请求的申请字节数(没有则为 NULL)

[`Expensive query`](/identify-expensive-queries.md) 新增字段 `mem_arbitration`,用于记录 SQL 等待资源耗时和当前订阅请求的信息,例如:

- `cost_time 2.1s, wait_start 1970-01-02 10:17:36.789 UTC, wait_bytes 123456789123 Bytes (115.0 GB)`

[`STATEMENTS_SUMMARY`](/statement-summary-tables.md):表 `statements_summary`、`statements_summary_history`、`cluster_statements_summary`、`cluster_statements_summary_history` 新增以下字段,[TiDB Dashboard SQL 语句分析执行详情页面](/dashboard/dashboard-statement-list.md) 中的 `Mean Mem Arbitration` 列也会显示该信息:

- `AVG_MEM_ARBITRATION`:平均 SQL 等待内存资源耗时
- `MAX_MEM_ARBITRATION`:最大 SQL 等待内存资源耗时

### 实践

默认系统变量 [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-从-v640-版本开始引入) 较小,启用内存仲裁模式后建议设置为 `95%`。

部署单节点 TiDB 场景

- 开启 `priority` 模式:绑定 OLTP 相关或重要 SQL 到高优先级,按需绑定其他 SQL 到中或低优先级
- 开启 `standard` 模式:遇到 `8180` 错误需等待并重试 SQL

部署多节点 TiDB 场景

- [1] 开启 `standard` 模式
- 遇到 `8180` 错误则重试 SQL 到其他 TiDB 节点

- [2] 开启 `priority` 模式
- 为 OLTP 相关或重要 SQL 绑定高优先级,按需绑定其他 SQL 到中或低优先级
- 通过 [`max_execution_time`](/system-variables.md#max_execution_time) 限制 SQL 最大执行时间
- 遇到超时或 `8180` 错误则重试 SQL 到其他 TiDB 节点
- 可通过设置 [`tidb_mem_arbitrator_wait_averse`](/system-variables.md#tidb_mem_arbitrator_wait_averse-从-v900-版本开始引入) 使 SQL 尽快重试到内存资源充足的节点

- [3] TiDB 实例分组
- 各组内通过配置文件参数 `instance.tidb_mem_arbitrator_mode` 设置 TiDB 实例内存管理模式
- 各组内通过配置文件参数 `instance.tidb_mem_arbitrator_soft_limit` 按需设置 TiDB 实例内存资源份额上限
- 按需分发 SQL 到不同组,并按照上述不同模式处理

保障重要 SQL 执行

- 通过 [`tidb_mem_arbitrator_query_reserved`](/system-variables.md#tidb_mem_arbitrator_query_reserved-从-v900-版本开始引入) 保障 SQL 的内存资源隔离性
- 绑定高优先级的资源组
- 设置 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 为较大值以免 SQL 执行被中断
- 保底方案为设置 [`tidb_mem_arbitrator_wait_averse`](/system-variables.md#tidb_mem_arbitrator_wait_averse-从-v900-版本开始引入) 为 `nolimit` 并承担相关风险
63 changes: 63 additions & 0 deletions system-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -3328,6 +3328,69 @@ v5.0 后,用户仍可以单独修改以上系统变量(会有废弃警告)
- 单位:线程
- TiFlash 中 request 执行的最大并发度。默认值为 `-1`,表示该系统变量无效,此时最大并发度取决于 TiFlash 配置项 `profiles.default.max_threads` 的设置。`0` 表示由 TiFlash 系统自动设置该值。

### `tidb_mem_arbitrator_mode` <span class="version-mark">从 v9.0.0 版本开始引入</span>

> **警告:**
>
> 该变量控制的功能为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。

- 作用域:GLOBAL
- 是否持久化到集群:是
- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否
- 类型:枚举型
- 默认值:`disable`
- 可选值:`disable`,`standard`, `priority`
- 该变量用于设置 TiDB 实例的全局内存管理模式,详见 [TiDB 内存控制](/configure-memory-usage.md#内存仲裁模式):
- `disable` 表示禁用内存仲裁模式,保持内存资源 [先使用后上报](/system-variables.md#tidb_server_memory_limit-从-v640-版本开始引入) 的机制。
- `standard` 表示启用标准内存仲裁模式。SQL 需要使用内存资源时,先向内存仲裁者进行订阅,成功后再分配内存资源。当订阅内存资源失败后,SQL 终止执行。
- `priority` 表示启用基于优先级的内存仲裁模式。SQL 需要使用内存资源时,先向内存仲裁者进行订阅,成功后再分配内存资源。TiDB 根据 SQL 的 [资源组优先级](/information-schema/information-schema-resource-groups.md) 处理内存资源订阅请求。

### `tidb_mem_arbitrator_query_reserved` <span class="version-mark">从 v9.0.0 版本开始引入</span>

> **警告:**
>
> 该变量控制的功能为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。

- 作用域:SESSION
- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是
- 类型:整数型
- 默认值:`0`
- 单位:字节
- 范围:`[0, 9223372036854775807]`
- 当启用内存仲裁模式后,该变量设置 SQL 执行前预先订阅指定数量的内存资源份额,详见 [TiDB 内存控制](/configure-memory-usage.md#手动保障内存安全)。

### `tidb_mem_arbitrator_soft_limit` <span class="version-mark">从 v9.0.0 版本开始引入</span>

> **警告:**
>
> 该变量控制的功能为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。

- 作用域:GLOBAL
- 是否持久化到集群:是
- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否
- 类型:字符串
- 默认值:`0`
- 可选值:`0`,浮点数 `(0, 1]`,整数 `(1, 9223372036854775807]`
- 当启用内存仲裁模式后,该变量设置 TiDB 实例的内存资源份额上限,详见 [TiDB 内存控制](/configure-memory-usage.md#手动保障内存安全)。
- `0`:默认资源份额上限为 [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-从-v640-版本开始引入) 值的 `95%`
- 浮点数 `(0, 1]`:指定比率,资源份额上限为 `tidb_mem_arbitrator_soft_limit *` [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-从-v640-版本开始引入)
- 整数 `(1, 9223372036854775807]`:指定字节数

### `tidb_mem_arbitrator_wait_averse` <span class="version-mark">从 v9.0.0 版本开始引入</span>

> **警告:**
>
> 该变量控制的功能为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。

- 作用域:SESSION
- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否
- 类型:枚举型
- 默认值:`0`
- 可选值:`0`,`1`,`nolimit`
- 当启用内存仲裁模式后,该变量控制 SQL 等待内存资源的相关行为,详见 [TiDB 内存控制](/configure-memory-usage.md#内存仲裁模式)。
- `1`:`priority` 模式下,SQL 订阅内存资源时自动绑定高优先级,全局内存资源不足时就终止执行而非阻塞式等待
- `nolimit`:SQL 使用内存资源不受限制,可能导致 TiDB 实例内存风险

### `tidb_mem_oom_action` <span class="version-mark">从 v6.1.0 版本开始引入</span>

- 作用域:GLOBAL
Expand Down