热点更新:多热点更新 Hint

最近更新时间:2026-07-01 14:27:31

我的收藏

功能简介

云数据库 MySQL 在 MySQL 8.0 20260512 版本中,新增了两个 SQL Hint,用于支持在单个事务内更新多个热点行,或在同一事务内多次访问同一热点行。本文为您重点说明这两个 Hint 的使用方式。
Hint 名称
作用范围
用途
TXSQL_FORCE_LOCK
事务级
在一个事务里更新多个不同热点行
TXSQL_FORCE_LOCK_INDEPENDENT_GROUP
单热点行级
允许同一事务对同一热点行进行多次访问

使用说明

语法格式

Hint 使用 MySQL 标准的 /*+ ... */ 语法,紧跟在 UPDATE / INSERT / DELETE 关键字之后:
UPDATE /*+ TXSQL_FORCE_LOCK */ table_name SET col = ... WHERE ...;
UPDATE /*+ TXSQL_FORCE_LOCK TXSQL_FORCE_LOCK_INDEPENDENT_GROUP */ table_name SET col = ... WHERE ...;

关键放置规则(请务必遵守)

TXSQL_FORCE_LOCK 必须放在事务的第一条 DML 语句上。
放对位置:整个事务进入 FORCE_LOCK 模式,后续 DML 不需要再带 Hint。
放在非首条 DML:Hint 被忽略并打 warning,事务仍按老的约束执行。
TXSQL_FORCE_LOCK_INDEPENDENT_GROUP 必须放在事务首次访问目标热点行的那条 DML 上。
该 Hint 只有在事务已经是 TXSQL_FORCE_LOCK 时才生效,否则会在解析期被丢弃并打 warning。
目标热点行的属性在首次访问时即一次性确定;后续再次访问即使带上 Hint,也会被视为「同事务内二次访问同一热点行」,从而导致事务回滚。
Hint 不跨事务、不跨语句继承,事务结束后自动失效。

INDEPENDENT_GROUP 不同放置位置的实际表现

放置位置
实际效果
事务第一次访问行 X 的 DML 上
行 X 进入独立组,本事务对行 X 的后续访问全部放行
事务第二次及之后访问行 X 的 DML 上
Hint 等同于没写:行 X 在第一次访问时已被记录为「非独立组」,本次访问被判为「二次访问同一热点行」,事务回滚
当前事务不是 TXSQL_FORCE_LOCK 事务
解析期 warning + 丢弃,按普通语句处理

使用场景与完整示例

场景1:单事务更新多个不同热点行

适用:需要在一个事务内同时修改多行热点数据(例如批量扣减不同账户余额)。
做法:只在事务的第一条 DML 上加 TXSQL_FORCE_LOCK,后续 DML 不需要再带 Hint。
BEGIN;
-- ① 第一条 DML 必须带 TXSQL_FORCE_LOCK
UPDATE /*+ TXSQL_FORCE_LOCK */ t_account SET balance = balance + 100 WHERE id = 1;

-- ② 第二条及后续 DML 不需要再带 hint,事务已经处于 force_lock 模式
UPDATE t_account SET balance = balance + 100 WHERE id = 2;
UPDATE t_account SET balance = balance + 100 WHERE id = 3;
COMMIT;

场景2:单事务对同一热点行多次访问

适用:需要在一个事务内对同一行热点数据做多次读写(例如先扣减、再校验、再调整)。
做法:在事务首次访问该热点行的那条 DML 上,同时带上 TXSQL_FORCE_LOCK 与 TXSQL_FORCE_LOCK_INDEPENDENT_GROUP;后续访问不再带 Hint。
BEGIN;
-- ① 首次访问 id=1,必须同时带两个 hint
UPDATE /*+ TXSQL_FORCE_LOCK TXSQL_FORCE_LOCK_INDEPENDENT_GROUP */
t_account SET balance = balance + 1 WHERE id = 1;

-- ② 之后对 id=1 的访问不需要、也不应该再带 INDEPENDENT_GROUP
UPDATE t_account SET balance = balance + 1 WHERE id = 1;
COMMIT;

反例:INDEPENDENT_GROUP 漏在首次访问

以下为错误用法示例,事务会回滚:
BEGIN;
-- 首次访问 id=1 时漏掉了 INDEPENDENT_GROUP
UPDATE /*+ TXSQL_FORCE_LOCK */ t_account SET balance = balance + 1 WHERE id = 1;

-- 在第二次访问时才补上 INDEPENDENT_GROUP —— 已经太晚
-- 此时 id=1 已被记录为「非独立组」,本条会被判为「二次访问同一热点行」,事务回滚
UPDATE /*+ TXSQL_FORCE_LOCK_INDEPENDENT_GROUP */
t_account SET balance = balance + 1 WHERE id = 1;
COMMIT;

使用约束

单事务最多参与到10个热点行(受 undo 页固定持久化区容量限制),超出会回滚事务并打 warning。
TXSQL_FORCE_LOCK 必须放事务首条 DML;TXSQL_FORCE_LOCK_INDEPENDENT_GROUP 必须放对应热点行的首次访问 DML。放错位置会失效或事务回滚。
Hint 不会跨事务 / 跨语句继承,每个事务 / 语句都需要重新声明。
说明:
使用功能前建议在测试环境对业务事务进行验证,确认 Hint 已实际生效(可通过 SHOW WARNINGS 排查是否因放置位置错误被忽略)。

补充说明

本版本同时优化了热点行冷却时的性能回退问题:通过队首等待者自唤醒、以及基于滑动窗口的冷却机制,解决了热点流量从大变小时不必要的事务延迟。该优化对业务无感知、无需改造。