脏读、不可重复读、幻读示例
1. 脏读 (Dirty Read)
场景:事务A读取了事务B未提交的数据修改。
-- 事务A BEGIN TRANSACTION; UPDATE accounts SET balance = balance - 100 WHERE id = 1; -- 账户1扣除100元,未提交-- 事务B BEGIN TRANSACTION; SELECT balance FROM accounts WHERE id = 1; -- 读取到未提交的修改(脏读) COMMIT;-- 事务A ROLLBACK; -- 事务A回滚,但事务B已经读取了错误的数据
2. 不可重复读 (Non-repeatable Read)
场景:同一事务内两次读取同一数据,结果不同。
-- 事务A BEGIN TRANSACTION; SELECT balance FROM accounts WHERE id = 1; -- 第一次读取,返回1000-- 事务B BEGIN TRANSACTION; UPDATE accounts SET balance = balance - 100 WHERE id = 1; COMMIT;-- 事务A SELECT balance FROM accounts WHERE id = 1; -- 第二次读取,返回900(与第一次不同) COMMIT;
3. 幻读 (Phantom Read)
场景:同一事务内两次查询同一条件,返回的行数不同。
-- 事务A BEGIN TRANSACTION; SELECT * FROM accounts WHERE balance > 1000; -- 第一次查询返回2条记录-- 事务B BEGIN TRANSACTION; INSERT INTO accounts(id, balance) VALUES (3, 1500); -- 新增一个高余额账户 COMMIT;-- 事务A SELECT * FROM accounts WHERE balance > 1000; -- 第二次查询返回3条记录(出现幻行) COMMIT;
隔离级别与这些问题
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ UNCOMMITTED | 可能 | 可能 | 可能 |
READ COMMITTED | 避免 | 可能 | 可能 |
REPEATABLE READ | 避免 | 避免 | 可能 |
SERIALIZABLE | 避免 | 避免 | 避免 |