mysql事务中如何避免幻读_mysql隔离机制解析-mysql教程

幻读是事务中两次范围查询结果行数不一致,因其他事务插入/删除导致;不可重复读是同一行数据值被修改。MySQL的REPEATABLE READ通过间隙锁抑制幻读但未消除其语义,SERIALIZABLE虽彻底解决却牺牲并发,合理索引与SQL优化更实用。

幻读到底是什么,和不可重复读有什么区别

幻读不是“看到幻觉”,而是指事务中两次 SELECT 同一范围数据,第二次多出(或少掉)了新插入(或删除)的行——这些行在第一次查询时并不存在,但被别的事务提交了。关键在于:它针对的是「范围查询」,比如 WHERE age > 25 或 SELECT * FROM user WHERE status = 1,而不是单行主键查询。

不可重复读是查同一行,值变了;幻读是查一个范围,行数变了。很多人混淆,是因为 MySQL 默认的 REPEATABLE READ 隔离级别下,InnoDB 用间隙锁(Gap Lock)+ 行锁模拟出“无幻读”效果,但这只是表象——它没真正消除幻读语义,只是把并发写冲突提前拦住了。

MySQL 的 REPEATABLE READ 真的能防止幻读吗

在 InnoDB 中,REPEATABLE READ 下普通 SELECT 是快照读(Snapshot Read),不加锁,靠 MVCC 版本链避免脏读和不可重复读;但只要涉及当前读(如 SELECT ... FOR UPDATE、UPDATE、DELETE),InnoDB 就会加临键锁(Next-Key Lock),即「行锁 + 间隙锁」,从而封锁索引区间,阻止其他事务在该范围内插入新记录。

这意味着:

  • 如果你只用纯 SELECT(无锁读),幻读不会发生——因为看到的是事务开始时的一致快照
  • 但如果你执行 SELECT ... FOR UPDATE 查范围,然后另一个事务尝试 INSERT 进这个间隙,会被阻塞或报死锁——这不是“防止幻读”,而是“用锁压制了幻读发生的条件”
  • 一旦你没走索引(比如 WHERE name LIKE '%abc%'),间隙锁退化为全表锁,性能雪崩

想真正规避幻读,必须用 SERIALIZABLE 吗

不用。MySQL 的 SERIALIZABLE 确实会对所有 SELECT 自动加上 LOCK IN SHARE MODE,变成串行执行,彻底杜绝幻读,但代价极高:并发能力几乎归零,且容易触发大量锁等待。

更务实的做法是:

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » mysql事务中如何避免幻读_mysql隔离机制解析-mysql教程
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4030682+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4030682+
  • 本周更新: 0+
  • 最后更新: 2026-03-16