

新闻资讯
技术学院脏读、不可重复读和幻读是MySQL并发事务中因隔离级别不足导致的三类数据不一致问题:脏读指读取未提交数据;不可重复读指同一行两次读取结果不同;幻读指相同条件查询返回行数变化。
脏读、不可重复读和幻读,是 MySQL 多事务并发时因隔离级别不足引发的三类典型数据不一致问题。它们本质都是“一个事务看到了另一个事务不该让它看到的状态”,区别在于看到的是什么、什么时候看到、以及影响范围。
事务 A 修改了一行数据但尚未提交,事务 B 此时读取了这行被修改后的值;如果随后 A 回滚,B 读到的就是一条根本不存在的“假数据”。这就是脏读。
例如:
UPDATE account SET balance = 50 WHERE id = 1;(未 COMMIT)SELECT balance FROM account WHERE id = 1;,查到 balance = 50ROLLBACK,balance 实际仍是 100脏读只在 READ UNCOMMITTED 隔离级别下发生,MySQL 默认不启用该级别。
事务 A 在同一个事务内两次读取同一行记录,中间事务 B 修改并提交了该行,导致 A 第二次读到的是新值。重点是“同一行被改了”。
例如:
SELECT status FROM order WHERE id = 1001; → 返回 'pending'UPDATE order SET status = 'shipped' WHERE id = 1001; COMMIT;
这种“读-写-再读”的不一致,在 READ COMMITTED 级别仍可能发生,但 REPEATABLE READ(MySQL 默认)通过 MVCC 机制避免了它。
事务 A 按条件做范围查询(如 WHERE amount > 100),事务 B 在此期间插入或删除了符合该条件的新行并提交,A 再次查询时发现多了一条或少了一条——就像凭空出现或消失的“幻影”。
例如:
SELECT * FROM payment WHERE created_at > '2025-12-01'; 得到 12 条COMMIT
注意:幻读不是某一行内容变了,而是“符合条件的行集合”发生了变化。MySQL 的 REPEATABLE READ 能防止大部分幻读(靠间隙锁+Next-Key Lock),但严格意义上的幻读(如 INSERT 后立刻 SELECT FOR UPDATE)在某些场景仍存在,SERIALIZABLE 才能彻底杜绝。
MySQL 四个级别逐级增强
,也逐级牺牲并发性能:
实际项目中,90% 以上用 REPEATABLE READ 即可,关键逻辑可通过显式加锁(如 SELECT ... FOR UPDATE)或应用层幂等设计进一步兜底。