MySQL 是怎么解决幻读的?

MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它很大程度上避免幻读现象(并不是完全解决了,详见这篇),解决的方案有两种:
针对 快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。
针对当前读(select ... for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。

什么条件下会触发当前读呢:
SELECT ... FOR UPDATE:这个语句会对选中的行加上排他锁(X锁),其他事务不能修改这些行,直到当前事务提交或回滚。这时候读取的是最新的数据,所以是当前读。

SELECT ... LOCK IN SHARE MODE:这个语句会对选中的行加上共享锁(S锁),允许其他事务读取这些行,但不能修改,直到锁释放。同样,这里读取的是最新提交的数据,属于当前读。

UPDATE语句:当执行UPDATE操作时,InnoDB需要先找到要更新的行,这时候会进行当前读,获取最新的数据并对这些行加锁,确保在更新过程中数据不被其他事务修改。

DELETE语句:和UPDATE类似,DELETE操作需要先定位到要删除的行,这时也会触发当前读,加锁以防止其他事务修改这些行。

INSERT ... ON DUPLICATE KEY UPDATE:当插入数据时,如果发生唯一键冲突,会执行更新操作,这时候的更新部分同样会触发当前读。

posted @ 2025-02-26 14:54  lipu123  阅读(31)  评论(0)    收藏  举报