mysql串行化隔离级别通过读写全加锁实现完全隔离,读操作加共享锁和间隙锁防幻读,写操作加next-key锁,禁用mvcc快照读,确保事务严格串行执行。

MySQL 串行化(Serializable)隔离级别通过读写都加锁的方式实现完全隔离,本质上是让并发事务退化为串行执行,彻底避免脏读、不可重复读和幻读。
读操作加共享锁(S锁)
在 Serializable 下,所有 SELECT 语句默认等价于 SELECT ... LOCK IN SHARE MODE。这意味着:
- 事务读取某行时,会对其加上共享锁(S锁),其他事务不能对该行加排他锁(X锁),即无法 UPDATE/DELETE/INSERT 覆盖该行;
- 若查询涉及范围(如
WHERE age > 25),InnoDB 不仅锁住匹配的现有记录,还会加间隙锁(Gap Lock),防止其他事务在空隙中插入新数据,从而解决幻读; - 即使查询条件无匹配结果(例如查不到 age=99 的记录),只要索引能定位到间隙,也会对相应间隙加锁。
写操作加排他锁(X锁)
UPDATE、DELETE、INSERT 等写操作的行为与可重复读(RR)类似,但限制更严格:
- 修改已有行:加 record lock(行锁) + gap lock(间隙锁),组合为 next-key lock;
- 插入新行:需检查插入位置是否被其他事务的间隙锁覆盖,若被锁则阻塞等待;
- 没有索引支持的 WHERE 条件,可能升级为表级锁(table lock),进一步降低并发度。
间隙锁确保“无空子可钻”
幻读的本质是其他事务在“看不见的空隙”里插入了新行。Serializable 利用间隙锁封死这些空隙:
- 假设表中有 id = 10、20、30 三行,
SELECT * FROM t WHERE id > 15会加 next-key 锁,覆盖 (15,20]、(20,30] 和 (30,+∞) 这些间隙; - 此时另一个事务尝试
INSERT INTO t VALUES (25, ...)或INSERT INTO t VALUES (35, ...)都会被阻塞; - 锁范围是左开右闭区间,且依赖索引结构——主键索引和辅助索引的间隙划分方式不同,需结合执行计划分析。
不依赖 MVCC,纯锁机制保障一致性
不同于 RC 和 RR 级别大量使用 MVCC 提供快照读,Serializable 基本禁用非锁定读:
- 普通 SELECT 必然触发加锁,无法绕过锁直接读取历史版本;
- 即使显式使用
SELECT ... FOR UPDATE或LOCK IN SHARE MODE,行为也与默认 SELECT 一致,没有额外变化; - 事务提交前,所有锁持续持有,其他事务只能排队等待,真正实现“一个接一个”执行。
这种方式牺牲了并发性能,但换来的是最严格的逻辑一致性——只要事务能执行成功,其结果就等价于按某种顺序串行执行的结果。











