diff --git a/configure-memory-usage.md b/configure-memory-usage.md index 986f9b2551b5..465906bb9d3b 100644 --- a/configure-memory-usage.md +++ b/configure-memory-usage.md @@ -212,6 +212,109 @@ TiDB 支持对执行算子的数据落盘功能。当 SQL 的内存使用超过 9 rows in set (1 min 37.428 sec) ``` +## 全局内存管理架构 + +TiDB 从 v9.0.0 开始引入全局内存管理框架 `Global Memory Arbitrator`,可通过系统变量 [`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 实例中唯一的仲裁者统筹内存资源。 + +仲裁者会通过终止 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。返回错误中 `reason` 字段为 `CANCEL(out-of-quota & standard-mode)`。 + +### `priority` 模式 + +SQL 运行过程中会动态地向仲裁者订阅内存资源,仲裁者根据 SQL 的[资源组优先级](/information-schema/information-schema-resource-groups.md) (`LOW | MEDIUM | HIGH`) 处理订阅请求。 + +- 所有请求按照优先级从高到低排队等待资源,同级别请求按照发起顺序排序 +- 当全局内存资源不足时,仲裁者按顺序(优先级从低到高,内存使用量从大到小)终止低优先级 SQL,回收资源来满足高优先级 SQL + - 如果所有 SQL 的优先级相同,仲裁者会调度资源直到所有 SQL 运行完,可能因此导致部分 SQL 延迟明显增大 + - 返回错误中 `reason` 字段为 `CANCEL(out-of-quota & priority-mode)` + +如果需要 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% 这一阈值时,仲裁者开始处理内存风险。如果内存用量短期无法低于到安全线或者内存使用速率过小,仲裁者会按顺序(优先级从低到高,内存使用量从大到小)强制终止 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 实例内存风险。 + +### 手动保障内存安全 + +通过系统变量 [`tidb_mem_arbitrator_soft_limit`](/system-variables.md#tidb_mem_arbitrator_soft_limit-从-v900-版本开始引入) 或 TiDB 配置文件参数 `instance.tidb_mem_arbitrator_soft_limit` 可以设置 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 等待内存资源的总耗时。 + +[`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` 新增字段以下字段: + +- `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` 并承担内存风险 + ## 其它 ### 设置环境变量 `GOMEMLIMIT` 缓解 OOM 问题 diff --git a/system-variables.md b/system-variables.md index 71dc3041fec3..f06c4c5860d9 100644 --- a/system-variables.md +++ b/system-variables.md @@ -3328,6 +3328,71 @@ v5.0 后,用户仍可以单独修改以上系统变量(会有废弃警告) - 单位:线程 - TiFlash 中 request 执行的最大并发度。默认值为 `-1`,表示该系统变量无效,此时最大并发度取决于 TiFlash 配置项 `profiles.default.max_threads` 的设置。`0` 表示由 TiFlash 系统自动设置该值。 +### `tidb_mem_arbitrator_mode` 从 v9.0.0 版本开始引入 + +> **警告:** +> +> 该变量控制的功能为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 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` 和 `priority` 为先订阅后分配模式: + - `standard`:SQL 订阅内存资源失败后终止执行 + - `priority`:TiDB 根据 SQL 的[资源组优先级](/information-schema/information-schema-resource-groups.md) 处理内存资源订阅任务 + +### `tidb_mem_arbitrator_query_reserved` 从 v9.0.0 版本开始引入 + +> **警告:** +> +> 该变量控制的功能为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +- 作用域:SESSION +- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 类型:整数型 +- 默认值:`0` +- 单位:字节 +- 范围:`[0, 9223372036854775807]` +- 当通过 [`tidb_mem_arbitrator_mode`](/system-variables.md#tidb_mem_arbitrator_mode-从-v900-版本开始引入) 启用先订阅后分配的全局内存管理模式后,该变量设置 SQL 执行前预先订阅指定数量的内存资源份额,详见 [TiDB 内存控制](/configure-memory-usage.md#全局内存管理架构)。 + +### `tidb_mem_arbitrator_soft_limit` 从 v9.0.0 版本开始引入 + +> **警告:** +> +> 该变量控制的功能为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 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_mem_arbitrator_mode`](/system-variables.md#tidb_mem_arbitrator_mode-从-v900-版本开始引入) 启用先订阅后分配的全局内存管理模式后,该变量设置 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` 从 v9.0.0 版本开始引入 + +> **警告:** +> +> 该变量控制的功能为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +- 作用域:SESSION +- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 类型:枚举型 +- 默认值:`0` +- 可选值:`0`,`1`,`nolimit` +- 当通过 [`tidb_mem_arbitrator_mode`](/system-variables.md#tidb_mem_arbitrator_mode-从-v900-版本开始引入) 启用先订阅后分配的全局内存管理模式后,该变量控制 SQL 避免阻塞式等待内存资源的相关属性,详见 [TiDB 内存控制](/configure-memory-usage.md#全局内存管理架构)。 + - `0`:无相关属性 + - `1`:`priority` 模式下,SQL 订阅内存资源时自动绑定高优先级,全局内存资源不足时就执行取消 (Cancel) 操作而非等待 + - `nolimit`:SQL 使用内存资源不受限制,可能导致 TiDB 实例内存风险 + ### `tidb_mem_oom_action` 从 v6.1.0 版本开始引入 - 作用域:GLOBAL