读未提交(read uncommitted)允许事务读取其他事务未提交的数据,必然导致脏读,即读到可能被回滚的错误数据,引发业务逻辑错乱,生产环境必须禁用。

读未提交(READ UNCOMMITTED)是事务隔离级别中最低的一档,它允许一个事务读取另一个事务尚未提交的中间状态数据。这种“放行”看似提升了并发读取效率,实则埋下了严重的脏读隐患——即读到了本不该存在、随时可能被回滚掉的“幻影数据”。
脏读到底发生了什么?
脏读的本质是:事务 A 正在修改某条记录(比如把用户余额从 100 元改成 200 元),但还没 commit;此时事务 B 执行 SELECT,直接读到了这个 200 元;紧接着事务 A 因校验失败执行 rollback,余额恢复为 100 元;而事务 B 已经基于错误的 200 元做了后续逻辑(比如发放了对应额度的优惠券),导致业务结果错乱且无法自洽。
为什么 READ UNCOMMITTED 会纵容脏读?
它不加任何读锁,也不依赖 MVCC 快照机制。事务 B 的读操作完全绕过事务 A 的写事务状态,直连最新数据页。数据库既不阻塞它,也不做版本判断,相当于把未提交的“草稿”当成了正式内容暴露出去。
典型风险场景举例
- 薪资误发:HR 事务正将张三工资从 15000 改为 18000,未提交;张三查薪看到 18000,信以为真并提前消费;HR 发现输错后回滚,张三实际只拿 15000,却已欠债。
- 库存超卖:订单事务扣减商品库存到 -1(尚未提交),另一并发查询读到 -1,判定“已售罄”,触发下架逻辑;但原订单最终回滚,库存恢复正常,系统却已错误下架。
- 风控误判:反欺诈服务读到某用户刚被标记为“高风险”(事务未提交),立即冻结账户;随后该标记因误报被撤回,但冻结动作已不可逆执行。
如何规避?
生产环境应禁用 READ UNCOMMITTED。即使对性能敏感,也至少升至 READ COMMITTED——它通过 MVCC 或语句级快照,确保只读已落地的数据。若需更高一致性,再按业务需要选用 REPEATABLE READ 或 SERIALIZABLE。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











