功能简介
云数据库 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_LOCKUPDATE /*+ 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,必须同时带两个 hintUPDATE /*+ TXSQL_FORCE_LOCK TXSQL_FORCE_LOCK_INDEPENDENT_GROUP */t_account SET balance = balance + 1 WHERE id = 1;-- ② 之后对 id=1 的访问不需要、也不应该再带 INDEPENDENT_GROUPUPDATE t_account SET balance = balance + 1 WHERE id = 1;COMMIT;
反例:INDEPENDENT_GROUP 漏在首次访问
以下为错误用法示例,事务会回滚:
BEGIN;-- 首次访问 id=1 时漏掉了 INDEPENDENT_GROUPUPDATE /*+ 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 排查是否因放置位置错误被忽略)。补充说明
本版本同时优化了热点行冷却时的性能回退问题:通过队首等待者自唤醒、以及基于滑动窗口的冷却机制,解决了热点流量从大变小时不必要的事务延迟。该优化对业务无感知、无需改造。