一文读懂数据库的四种事务隔离级别(含原理 + 实例 + 优缺点)


一文读懂数据库的四种事务隔离级别(含原理 + 实例 + 优缺点)

在并发环境下操作数据库时,事务隔离性(Isolation) 是保证数据正确性的重要手段。数据库通过设置“隔离级别”来控制不同事务之间的可见性,防止出现数据不一致的问题。

本篇文章将带你系统掌握:

  • 四种隔离级别的含义
  • 各自能解决哪些并发问题
  • 优缺点对比与适用场景
  • MySQL & Oracle 中的实现方式

什么是事务隔离级别?

事务(Transaction)有四大特性:ACID —— 原子性、一致性、隔离性、持久性。
其中,隔离性用来解决多个事务并发访问数据库时,可能出现的“脏读”、“不可重复读”、“幻读”等问题。

为了权衡性能与数据一致性,数据库提供了四种隔离级别(由低到高):

隔离级别 能否读未提交数据 能否发生不可重复读 能否发生幻读
Read Uncommitted ✅ 可以 ✅ 可以 ✅ 可以
Read Committed ❌ 不可 ✅ 可以 ✅ 可以
Repeatable Read ❌ 不可 ❌ 不可 ✅ 可以(部分可)
Serializable ❌ 不可 ❌ 不可 ❌ 不可

1️⃣ Read Uncommitted(读未提交)

定义:

允许一个事务读取另一个尚未提交的事务修改的数据

❗问题:

  • 可能导致 脏读(Dirty Read);
  • 数据存在被回滚的风险。

示例:

T1: UPDATE user SET balance = 0 WHERE id = 1; -- 未提交
T2: SELECT balance FROM user WHERE id = 1; → 得到 0
T1: ROLLBACK;

T2 读到的是被回滚掉的数据,属于“脏”。

✅ 特点:

  • ✅ 性能高;
  • ❌ 数据一致性差,几乎不用于生产环境。

2️⃣ Read Committed(读已提交)

定义:

一个事务只能读取到其他事务已提交的数据

✅ 解决问题:

  • ✔️ 能防止脏读。

❗仍存在的问题:

  • ❌ 不能防止 不可重复读
  • ❌ 不能防止 幻读

示例(不可重复读):

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 两次读到的值不同,不可重复。

✅ 特点:

  • Oracle 默认隔离级别;
  • ✅ 性能尚可;
  • ❌ 可读性不强,对分析类场景不友好。

3️⃣ Repeatable Read(可重复读)

定义:

保证在一个事务内,多次读取同一数据记录时,结果是一样的。

✅ 解决问题:

  • ✔️ 防止脏读;
  • ✔️ 防止不可重复读。

❗仍可能的问题:

  • ❌ 幻读仍可能发生(如对范围查询结果插入新记录);
  • ✅ 但在 MySQL InnoDB 引擎中已通过 MVCC + 间隙锁 避免幻读

示例(MySQL中避免幻读):

T1: SELECT * FROM orders WHERE amount > 100;
T2: INSERT INTO orders (id, amount) VALUES (6, 200); COMMIT;
T1: 再次执行查询,仍为第一次结果(避免幻读)

MySQL 使用“间隙锁”避免其他事务插入,防止幻读。

✅ 特点:

  • ✅ MySQL 默认隔离级别(InnoDB);
  • ✅ 性能与一致性兼顾;
  • ✅ 适合大部分业务场景。

4️⃣ Serializable(可串行化)

定义:

所有事务依次执行,串行排队,完全隔离。

✅ 解决问题:

  • ✔️ 防止脏读;
  • ✔️ 防止不可重复读;
  • ✔️ 防止幻读。

示例:

任何时候只能一个事务操作表,其它事务等待锁释放,完全不会读到被修改或新增的数据。

❗缺点:

  • ❌ 并发性能极差;
  • ❌ 容易造成大量事务阻塞;
  • ❌ 实际业务中使用较少,仅在金融等高一致性系统采用。

五、四种隔离级别对比总结表

隔离级别 脏读 不可重复读 幻读 性能 一致性
Read Uncommitted ❌ 有 ❌ 有 ❌ 有 ✅ 高 ❌ 差
Read Committed ✅ 无 ❌ 有 ❌ 有 ✅ 中 ❌ 一般
Repeatable Read ✅ 无 ✅ 无 ❌ MySQL无 ✅ 中 ✅ 较好
Serializable ✅ 无 ✅ 无 ✅ 无 ❌ 差 ✅ 强

六、MySQL 与 Oracle 的实现机制

数据库 默认隔离级别 防幻读方法
MySQL (InnoDB) Repeatable Read MVCC + 间隙锁(Gap Lock)
Oracle Read Committed Serializable 才能防幻读

MySQL 的 Repeatable Read 是强化版

在 InnoDB 中,即使是 Repeatable Read 也能防止幻读:

  • ✅ 使用 MVCC 保证旧版本读取;
  • ✅ 对范围查询使用 间隙锁,防止新数据插入。

七、事务隔离级别设置(SQL)

✅ MySQL 设置事务隔离级别:

-- 查询当前隔离级别
SELECT @@tx_isolation;

-- 设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

✅ Oracle 设置事务隔离级别:

-- 设置为 SERIALIZABLE
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

✅ 八、开发建议

场景 推荐隔离级别 原因
读多写少系统(如 BI 查询) Repeatable Read 保证数据一致性,性能可接受
写操作频繁(高并发业务) Read Committed 避免幻读牺牲,兼顾性能
银行、转账等高一致性场景 Serializable 完全隔离,保证数据严谨

九、记忆口诀

  • 读未提交:谁改我都能看(性能最好,但不靠谱)
  • 读已提交:提交我才能看(Oracle 默认)
  • 可重复读:我读过的就不变(MySQL 默认)
  • 串行化:大家一个个来(最安全最慢)

十、结语

数据库的隔离级别并非越高越好,而是要在性能与一致性之间做权衡。掌握四种隔离级别的适用场景与原理,不仅能避免并发 bug,还能提高数据库系统的稳定性和可维护性。

如果你觉得这篇文章对你有帮助:
点个赞支持一下!
收藏起来回顾!
分享给你的朋友或同事吧!


你可能感兴趣的:(数据库)