欢迎您访问新疆栾骏商贸有限公司,公司主营电子五金轴承产品批发业务!
全国咨询热线: 400-8878-609

新闻资讯

技术学院

什么是脏读_mysql事务问题解析

作者:P粉6029986702026-01-02 00:00:00
脏读是指事务A读取到事务B修改但未提交的数据,若B回滚则A读取结果错误;仅在Read Uncommitted隔离级别下发生,MySQL默认Repeatable Read故不出现;应提升至Read Committed或更高隔离级别避免。

脏读,就是事务A读到了事务B改过但还没提交的数据。如果B后来回滚了,A读到的就完全是错的——这笔数据根本没真正发生过。

脏读发生的前提条件

它只会在最低的隔离级别下出现:Read Uncommitted(读未提交)。MySQL 默认是 Repeatable Read,所以默认不会脏读;但一旦显式设成 Read Uncommitted,就打开了这个风险口。

  • 事务B执行 UPDATE 或 DELETE,但没 COMMIT
  • 事务A此时执行 SELECT,且隔离级别允许读未提交
  • A拿到的是B中途写入的中间状态,不是数据库最终持久化的值

一个真实可复现的例子

假设账户表有一条记录:id=1, balance=100

  • 事务B开始:BEGIN; UPDATE account SET balance = 80 WHERE id = 1;(不提交)
  • 事务A开始(隔离级别为 READ UNCOMMITTED):SELECT balance FROM account WHERE id = 1; → 返回 80
  • 事务B执行 ROLLBACK; → 余额实际仍是 100
  • 但事务A已经按 80 做了后续计算(比如再扣10),结果算出 70,而真实余额是 100

为什么脏读危险?

它破坏的是“读一致性”底线:读操作不该依赖随时可能消失的临时状态。

  • 业务逻辑出错:比如风控系统基于脏余额放行交易,实际资金不足
  • 报表失真:统计任务读到未提交的订单量,导出错误日报
  • 连锁错误:下游服务用脏数据生成通知、触发回调,无法撤回

怎么避免脏读

最直接有效的方式是提升事务隔离级别:

  • READ COMMITTED:确保只读已提交的数据(InnoDB 默认支持,开销小)
  • REPEATABLE READ(MySQL InnoDB 默认):进一步保证同一事务内多次读一致
  • 不推荐靠 SELECT ... FOR UPDATE 或锁来防脏读——那是治标,改隔离级别才是治本