脏读是指事务读取了另一事务未提交且最终回滚的数据,导致读到“短暂存在、最终消失”的中间状态;MySQL默认隔离级别REPEATABLE READ通过MVCC避免脏读,仅READ UNCOMMITTED级别允许脏读。

脏读是指一个事务读取了另一个事务尚未提交的修改数据,而后者随后回滚,导致前者读到的数据在数据库中根本不存在。
脏读的核心特征
关键在于「未提交 + 被读取 + 后续回滚」三个环节同时发生。它不是数据被改错了,而是读到了一段“短暂存在、最终消失”的中间状态。
- 事务A更新某行余额为1000,但没执行COMMIT
- 事务B此时SELECT读到1000,并据此做业务判断(比如允许用户下单)
- 事务A因异常ROLLBACK,余额恢复为原始值(比如800)
- 事务B已基于1000做出的操作,就失去了数据依据
为什么MySQL默认不会脏读
MySQL InnoDB引擎默认隔离级别是REPEATABLE READ,该级别通过MVCC(多版本并发控制)机制自动规避脏读。即使在READ COMMITTED下,也只读已提交版本,同样不脏读。只有显式设为READ UNCOMMITTED时才会开放脏读能力——这在生产环境几乎不用。
脏读和不可重复读的区别
很多人混淆这两者,其实关键看数据是否“真正落地”:
- 脏读:读的是别人没提交过的数据,对方一回滚就没了
- 不可重复读:读的是别人已提交的数据,所以两次读结果不同,但每次都是真实有效的
如何验证或触发脏读(仅测试用)
若需观察脏读现象,可在会话中临时降级隔离级别:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
之后开启两个事务,让一个UPDATE不提交,另一个直接SELECT即可复现。但请勿在正式库中启用该级别。










