mysql不同隔离级别解决了什么问题_mysql并发现象解析

来源:这里教程网 时间:2026-02-28 20:48:59 作者:

读未提交(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
就是间隙锁的典型痕迹

真正难调的不是选哪个级别,而是理解每个级别背后锁怎么加、什么时候放、为什么卡住——尤其当业务混合了范围查询、非唯一索引和批量更新时。

相关推荐