脏读、不可重复读、幻读问题解析
三大并发问题概述 问题 定义 影响范围 解决隔离级别 脏读 读到未提交的数据 单行数据 READ COMMITTED 不可重复读 同一查询两次结果不同(UPDATE) 单行数据 REPEATABLE READ 幻读 范围查询两次结果不同(INSERT) 多行数据 SERIALIZABLE 1. 脏读(Dirty Read) 定义 读取到其他事务未提交的数据,如果该事务回滚,就会读到"脏"数据。 场景演示 -- 设置为最低隔离级别 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- 时间线:事务A和事务B并发执行 ┌─────────────────┬─────────────────────────────────┐ │ 事务A │ 事务B │ ├─────────────────┼─────────────────────────────────┤ │ START TRANSACTION│ │ │ │ START TRANSACTION │ │ SELECT balance │ │ │ FROM account │ │ │ WHERE id=1; │ │ │ -- 读到1000 │ │ │ │ UPDATE account │ │ │ SET balance=500 │ │ │ WHERE id=1; │ │ │ -- 未提交 │ │ SELECT balance │ │ │ FROM account │ │ │ WHERE id=1; │ │ │ -- 读到500(脏读)│ │ │ │ ROLLBACK; │ │ │ -- 余额回滚到1000 │ │ -- 但事务A已经基于 │ │ │ -- 500做决策,错误!│ │ │ COMMIT; │ │ └─────────────────┴─────────────────────────────────┘ 真实案例 -- 场景:电商库存扣减 -- 事务A:查询库存并下单 START TRANSACTION; SELECT stock FROM product WHERE id = 1001; -- 读到库存50 -- 事务B:库存更正(发现统计错误) START TRANSACTION; UPDATE product SET stock = 10 WHERE id = 1001; -- 实际只有10件 -- 未提交 -- 事务A继续 -- 基于库存50的判断,允许用户下单40件 INSERT INTO orders (product_id, quantity) VALUES (1001, 40); COMMIT; -- 事务B回滚 ROLLBACK; -- 库存恢复到50 -- 结果:用户下单40件,但实际库存只有10件,超卖! 解决方案 提高隔离级别到READ COMMITTED或更高: ...