读未提交允许脏读,可重复读通过mvcc防止脏读和不可重复读但幻读仍可能发生,串行化通过锁机制彻底避免三类问题但并发性能最低。

读未提交(READ UNCOMMITTED)下能看到别人还没 COMMIT 的数据
这是最低隔离级别,事务可以读到其他事务尚未提交的修改,也就是“脏读”。比如事务 A 更新了某行但没提交,事务 B 此时执行 SELECT 就可能拿到这个中间值。实际业务中极少使用,除非明确接受脏读且对一致性无要求(如某些实时日志分析场景)。MySQL 默认不启用该级别,需显式设置:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;注意:即使开了,InnoDB 仍会对部分操作加锁,不是完全无锁读。
可重复读(REPEATABLE READ)靠 MVCC 避免幻读但不彻底
MySQL 默认级别,通过多版本并发控制(MVCC)让事务内多次 SELECT 看到相同快照。它能防止脏读和不可重复读,但标准 SQL 定义的“幻读”——即同一查询条件返回新插入的行——在某些情况下仍会发生。例如事务 A 执行 SELECT * FROM t WHERE id > 10 得到 5 行,事务 B 插入一条 id = 15 并提交,事务 A 再查仍只有 5 行(MVCC 快照隔离),但如果事务 A 接着执行 UPDATE t SET name='x' WHERE id > 10,这条新插入的记录会被更新——这就是“幻读”的实际影响。要真正阻止,得用 SELECT ... FOR UPDATE 或调整为串行化。
串行化(SERIALIZABLE)用读锁堵死所有并发写
最高隔离级别,MySQL 会把所有普通 SELECT 隐式转成 SELECT ... LOCK IN SHARE MODE,读操作加共享锁,写操作加排他锁。这意味着读写、写写之间都会阻塞,彻底避免脏读、不可重复读、幻读。但代价是并发能力急剧下降,容易出现锁等待甚至死锁。常见于金融类强一致场景,但上线前必须压测确认吞吐是否达标。开启方式:
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;注意:如果应用里混用了显式锁(如
SELECT ... FOR UPDATE),和串行化叠加可能导致更长的锁持有时间。
不同级别对 UPDATE / DELETE 的锁行为差异很大
隔离级别不仅影响读,还决定写操作的锁粒度和持续时间。例如在可重复读下,UPDATE 语句会基于当前读(current read)加行锁,并可能触发间隙锁(gap lock)来防止幻插入;而在读已提交(READ COMMITTED)下,InnoDB 不用间隙锁(仅在唯一索引等少数情况例外),锁只加在命中的记录上,且事务一提交就释放。这导致:
- 读已提交更适合高并发写场景,但需接受不可重复读
- 可重复读更安全,但间隙锁可能引发意外锁冲突,比如
WHERE age BETWEEN 20 AND 30会锁住整个范围,哪怕表里目前没有 25 岁的记录 - 线上排查死锁时,
SHOW ENGINE INNODB STATUS输出里的lock_mode X locks gap before rec就是间隙锁的典型痕迹
真正难调的不是选哪个级别,而是理解每个级别背后锁怎么加、什么时候放、为什么卡住——尤其当业务混合了范围查询、非唯一索引和批量更新时。










