READ COMMITTED下UPDATE锁在语句执行完立即释放,不等到事务结束;仅对命中行加记录锁,禁用间隙锁,支持高并发插入,但需容忍不可重复读。

READ COMMITTED 下的锁只在语句执行期间存在
在 READ COMMITTED 隔离级别下,InnoDB 对 UPDATE 或 DELETE 语句加的行锁,会在该语句执行完就立刻释放,而不是等到整个事务结束。这意味着后续同事务内的其他语句(比如另一个 UPDATE)不会被前面语句的锁阻塞,其他事务也能更快获取到这些行的锁。
常见错误现象:在 REPEATABLE READ 下写一个长事务,中间执行了多次更新,结果发现其他事务在等第一句更新的锁,哪怕那句早就跑完了——这就是锁没及时释放导致的“假性阻塞”。
使用场景:订单状态批量变更、库存扣减后记录日志这类分步操作,用 READ COMMITTED 可避免前序语句锁住资源拖累后续并发。
普通 SELECT 不加锁,不阻塞写操作
READ COMMITTED 的快照读(即不带 FOR UPDATE 或 LOCK IN SHARE MODE 的 SELECT)完全不加锁,只依赖 MVCC 版本链读取已提交版本。这和 REPEATABLE READ 下某些场景会隐式加共享锁不同。
容易踩的坑:SELECT ... FOR UPDATE 在两种隔离级别下都加 X 锁,但 READ COMMITTED 中它只锁住实际扫描并命中的行;而 REPEATABLE READ 可能因间隙锁把整个索引区间锁住,导致插入新记录也被阻塞。
- 若查询条件无有效索引,
READ COMMITTED仍会逐行加锁(全表扫描+行锁),但不会升级为范围锁 - 只要业务能接受两次
SELECT返回不同结果(不可重复读),就不该为“一致性读”牺牲并发
不使用间隙锁,大幅降低死锁概率
InnoDB 在 READ COMMITTED 下默认禁用间隙锁(gap lock),只对匹配到的具体行加记录锁(record lock)。这意味着其他事务可以自由在间隙中插入新行,不会触发锁等待。
性能影响明显:秒杀场景中,大量用户同时插入新订单,若用 REPEATABLE READ,InnoDB 可能对 user_id = 123 对应的整个索引区间加临键锁(next-key lock),导致插入排队;换成 READ COMMITTED 后,只要不冲突同一行,插入几乎互不影响。
注意点:如果你显式用了 SELECT ... FOR UPDATE 并且 WHERE 条件是范围(如 WHERE created_at > '2026-09-01'),即使在 READ COMMITTED 下,InnoDB 也可能加间隙锁——这不是隔离级别失效,而是语义所需。
事务回滚成本更低,重试更轻量
锁持有时间越短,事务因锁等待超时或被选为死锁牺牲者而回滚的概率就越低;就算真回滚了,因为没长期持有锁,对其他事务的影响也小得多。
可观察现象:监控中 Innodb_row_lock_time_avg 和 Deadlocks 计数在切换到 READ COMMITTED 后通常明显下降,尤其在写密集型服务中。
真正容易被忽略的是:这个收益不是白来的——你需要确认业务逻辑是否真的能容忍不可重复读。比如报表类任务反复查同一张表,两次结果不一致可能引发校验失败;但订单状态流转、消息去重、计数器更新这类场景,基本不受影响。


















