在并发环境下操作数据库时,事务隔离性(Isolation) 是保证数据正确性的重要手段。数据库通过设置“隔离级别”来控制不同事务之间的可见性,防止出现数据不一致的问题。
本篇文章将带你系统掌握:
事务(Transaction)有四大特性:ACID —— 原子性、一致性、隔离性、持久性。
其中,隔离性用来解决多个事务并发访问数据库时,可能出现的“脏读”、“不可重复读”、“幻读”等问题。
为了权衡性能与数据一致性,数据库提供了四种隔离级别(由低到高):
隔离级别 | 能否读未提交数据 | 能否发生不可重复读 | 能否发生幻读 |
---|---|---|---|
Read Uncommitted | ✅ 可以 | ✅ 可以 | ✅ 可以 |
Read Committed | ❌ 不可 | ✅ 可以 | ✅ 可以 |
Repeatable Read | ❌ 不可 | ❌ 不可 | ✅ 可以(部分可) |
Serializable | ❌ 不可 | ❌ 不可 | ❌ 不可 |
允许一个事务读取另一个尚未提交的事务修改的数据。
T1: UPDATE user SET balance = 0 WHERE id = 1; -- 未提交
T2: SELECT balance FROM user WHERE id = 1; → 得到 0
T1: ROLLBACK;
T2 读到的是被回滚掉的数据,属于“脏”。
一个事务只能读取到其他事务已提交的数据。
T1: SELECT salary FROM employee WHERE id = 1; -- salary = 5000
T2: UPDATE employee SET salary = 7000 WHERE id = 1; COMMIT;
T1: SELECT salary FROM employee WHERE id = 1; -- salary = 7000
T1 两次读到的值不同,不可重复。
保证在一个事务内,多次读取同一数据记录时,结果是一样的。
T1: SELECT * FROM orders WHERE amount > 100;
T2: INSERT INTO orders (id, amount) VALUES (6, 200); COMMIT;
T1: 再次执行查询,仍为第一次结果(避免幻读)
MySQL 使用“间隙锁”避免其他事务插入,防止幻读。
所有事务依次执行,串行排队,完全隔离。
任何时候只能一个事务操作表,其它事务等待锁释放,完全不会读到被修改或新增的数据。
隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 | 一致性 |
---|---|---|---|---|---|
Read Uncommitted | ❌ 有 | ❌ 有 | ❌ 有 | ✅ 高 | ❌ 差 |
Read Committed | ✅ 无 | ❌ 有 | ❌ 有 | ✅ 中 | ❌ 一般 |
Repeatable Read | ✅ 无 | ✅ 无 | ❌ MySQL无 | ✅ 中 | ✅ 较好 |
Serializable | ✅ 无 | ✅ 无 | ✅ 无 | ❌ 差 | ✅ 强 |
数据库 | 默认隔离级别 | 防幻读方法 |
---|---|---|
MySQL (InnoDB) | Repeatable Read | MVCC + 间隙锁(Gap Lock) |
Oracle | Read Committed | Serializable 才能防幻读 |
在 InnoDB 中,即使是 Repeatable Read 也能防止幻读:
-- 查询当前隔离级别
SELECT @@tx_isolation;
-- 设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 设置为 SERIALIZABLE
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
场景 | 推荐隔离级别 | 原因 |
---|---|---|
读多写少系统(如 BI 查询) | Repeatable Read | 保证数据一致性,性能可接受 |
写操作频繁(高并发业务) | Read Committed | 避免幻读牺牲,兼顾性能 |
银行、转账等高一致性场景 | Serializable | 完全隔离,保证数据严谨 |
- 读未提交:谁改我都能看(性能最好,但不靠谱)
- 读已提交:提交我才能看(Oracle 默认)
- 可重复读:我读过的就不变(MySQL 默认)
- 串行化:大家一个个来(最安全最慢)
数据库的隔离级别并非越高越好,而是要在性能与一致性之间做权衡。掌握四种隔离级别的适用场景与原理,不仅能避免并发 bug,还能提高数据库系统的稳定性和可维护性。
如果你觉得这篇文章对你有帮助:
点个赞支持一下!
收藏起来回顾!
分享给你的朋友或同事吧!