MySQL默认REPEATABLE READ因间隙锁导致高并发阻塞,切READ COMMITTED可缓解但需全局配置+连接池+ORM协同生效,且必须配ROW格式binlog防主从不一致。

MySQL 默认的 REPEATABLE READ 隔离级别在高并发写场景下,会因间隙锁(gap lock)和临键锁(next-key lock)引发大量表级阻塞、死锁或 Lock wait timeout exceeded 错误——这不是配置错了,而是 RR 语义本身的代价。切到 READ COMMITTED(RC)能显著缓解,但必须按真实链路操作,不能只改一个参数。
为什么 SET GLOBAL 不生效?已连接会话不受影响
执行 SET GLOBAL transaction_isolation = 'READ-COMMITTED'; 后,新建立的连接会用 RC,但所有已在运行的应用连接仍保持原隔离级别(通常是 RR)。Spring、MyBatis 等框架在获取连接后,常会立即执行 SET SESSION TRANSACTION ISOLATION LEVEL ... 覆盖全局设置。
- 验证当前连接实际级别:连上后执行
SELECT @@transaction_isolation;,不是看@@global.transaction_isolation - Druid 连接池需显式配置
initConnectionSqls=SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED - HikariCP 要用
connection-init-sql,且必须确保该 SQL 在连接首次使用前执行 - 若 ORM 硬编码了
@Transactional(isolation = Isolation.REPEATABLE_READ),数据库层配置完全无效
RC 下 SELECT FOR UPDATE 为什么还锁不住“幻行”?
RC 解除了间隙锁,SELECT FOR UPDATE 只锁命中的**已有行**,不锁索引间隙。这意味着:事务 A 查出 10 条记录后,事务 B 插入 1 条并提交,A 再执行相同 SELECT FOR UPDATE 会看到这第 11 条,并对其加锁——A 原本的业务逻辑(比如“查无重复则插入”)就可能被绕过。
- 唯一约束未建好时,靠“先查再插”防重 → 必须补唯一索引,否则 RC 下必然脏插入
- 依赖两次查询结果一致做校验(如查余额 → 判定是否足够 → 扣款)→ RC 下窗口期暴露,必须改用
SELECT FOR UPDATE+ 显式加锁,且 WHERE 条件必须走索引 -
UPDATE ... WHERE id = ?在 RC 下不会锁间隙,但如果id是唯一索引且该值不存在,InnoDB 仍会加插入意向锁(insert intention lock),阻塞其他插入,这点常被忽略
binlog 格式不配 ROW,RC 就是定时炸弹
RC 隔离级别下,若 binlog_format 是 MIXED 或 STATEMENT,主从数据大概率不一致。因为 RC 的一致性读是语句级快照,而 STATEMENT 复制依赖主库执行时的上下文(如 NOW()、UUID()、自增 ID 分配),从库回放时语义已偏移。
- 必须执行
SET GLOBAL binlog_format = 'ROW';并确认从库也启用 ROW - 检查现有复制链:运行
SHOW SLAVE STATUS\G,确认Retrieved_Gtid_Set和Executed_Gtid_Set持续追平,避免切换后延迟跳变 - 旧版本 MySQL(如 5.6)不支持动态改 binlog_format,需重启 mysqld 并在 my.cnf 中固化
压测时重点盯什么?别只看 QPS
切 RC 后 QPS 上升不代表安全。真正要验证的是锁行为是否收敛、应用逻辑是否仍成立。
- 压测中执行
SHOW ENGINE INNODB STATUS\G,重点关注TRANSACTIONS段里的lock struct(s)数量和平均等待时间,对比 RR/RC 下差异 - 开启
innodb_status_output_locks = ON,让状态输出包含更细粒度的锁信息 - 慢查询日志里搜
SELECT.*FOR UPDATE和UPDATE.*WHERE,确认它们的 WHERE 是否都命中索引;没走索引的 UPDATE 在 RC 下会锁全表所有行,比 RR 更危险 - 业务日志中检查是否有“余额校验通过但扣款失败”“重复下单成功”等现象,这是 RC 下最隐蔽的逻辑断裂点
RC 不是万能解药,它是用“不可重复读”换“低锁冲突”。真正难的不是改配置,而是确认你的每一条“读-判-写”路径,在 RC 下是否仍闭环——尤其是那些没写进文档、靠经验维护的隐式一致性假设。

















