SET GLOBAL transaction_isolation = 'READ-COMMITTED'; SELECT @@transaction_isolation; SELECT COUNT(*) FROM performance_schema.data_locks;
同一套压测脚本,RR 下 data_locks 峰值 1.8 万行,平均锁等待 420 毫秒;切到 RC 后锁行数降到 3000,等待时间 90 毫秒。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。
原因不复杂,可重复读会给范围查询加间隙锁,锁住不存在的区间来防止幻读。读已提交只锁命中的记录,间隙不锁。锁的范围小了,冲突概率跟着降,代价是同一事务里两次范围查询可能看到不同的行。
围绕「隔离级别锁差异」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。
处理上按这个顺序:确认业务能接受不可重复读 再考虑切 RC;只对需要一致性快照的会话单独 set session 隔离级别;切完观察 data_locks 里的 LOCK_GAP 是否消失;用同一份压测数据对比两次的锁等待时间。
改完只确认一件事:压测时 data_locks 行数明显下降 锁等待回到百毫秒以内 业务查询结果没有出现异常。
