MySQL 解决幻读问题,主要依靠 隔离级别 和 MVCC(多版本并发控制) 机制,具体方式取决于使用的存储引擎(InnoDB 为主)和事务隔离级别。
幻读是啥?
幻读指的是:同一个事务中,前后两次执行相同的查询,却得到了不一样的结果(因为别的事务插入了新数据)。
MySQL 是怎么防的?
1. RR(Repeatable Read,可重复读) + MVCC
InnoDB 默认用的是 RR 隔离级别,配合 MVCC,能防止大多数幻读。
- MVCC 是通过记录多个版本的行来实现“快照读”(select时不加锁)。
- 对于普通的
SELECT
,用的是一致性视图,不会看到其他事务新插入的记录。
BUT:
- 如果你用的是
SELECT ... FOR UPDATE
或UPDATE
,就不再是“快照读”了,而是“当前读”,这时 MVCC 不能解决幻读。
2. 间隙锁(Gap Lock)
为了彻底解决幻读,InnoDB 在 RR 隔离级别下会使用 间隙锁:
- 举个例子:你执行了
SELECT * FROM user WHERE age > 30 FOR UPDATE;
,InnoDB 会给 age > 30 的范围加锁,防止其他事务在这个区间插入新记录,避免幻读。 - 间隙锁锁的不是某条记录,而是“记录之间的间隙”。
总结
场景 | 是否会幻读 | MySQL 如何防止 |
普通 | 不会 | MVCC(快照读) |
| 会 | 间隙锁 + RR 隔离级别 |