> 技术文档 > MySQL 事务隔离级别详解与应用场景分析_mysql事务隔离级别使用场景

MySQL 事务隔离级别详解与应用场景分析_mysql事务隔离级别使用场景

MySQL 事务隔离级别定义了多个事务并发执行时彼此之间的可见性,直接影响数据的一致性和并发性能。MySQL(特别是 InnoDB 引擎)支持以下 四种标准的事务隔离级别,它们从低到高分别是:


🔹 1. Read Uncommitted(读取未提交)

  • 特点:一个事务可以读取另一个事务未提交的数据。
  • 问题:可能会出现脏读(Dirty Read)
  • 示例
    • 事务 A 修改了一条记录但尚未提交;
    • 事务 B 能看到并读取这个未提交的修改;
    • 如果 A 回滚,B 得到的是不存在的值。

🔹 2. Read Committed(读取已提交)

  • 特点:只能读取已经提交的数据。
  • 解决问题:避免了脏读。
  • 问题:可能出现不可重复读(Non-repeatable Read)
  • 示例
    • 事务 A 先读取一条数据;
    • 事务 B 更新并提交该数据;
    • 事务 A 再次读取时,值发生变化。

🔹 3. Repeatable Read(可重复读)(MySQL 默认级别)

  • 特点:事务内多次读取同一条记录结果一致。
  • 解决问题:避免了脏读和不可重复读。
  • 问题:可能出现幻读(Phantom Read)
  • 示例
    • 事务 A 查询某条件下的多条数据;
    • 事务 B 插入符合该条件的新记录;
    • 事务 A 再次执行相同查询,结果多了一条。

🔹 4. Serializable(可串行化)

  • 特点:完全串行化执行,事务间完全隔离。
  • 解决问题:避免了幻读。
  • 缺点:并发性能最差,锁粒度大,容易造成锁等待。

🔄 各隔离级别对比总结表:

隔离级别 脏读 不可重复读 幻读 并发性能 Read Uncommitted ✅ 有 ✅ 有 ✅ 有 🔥 高 Read Committed ❌ 无 ✅ 有 ✅ 有 🔥🔥 高 Repeatable Read ❌ 无 ❌ 无 ✅ 有(MySQL 内部通过间隙锁解决) ⚖️ 中等 Serializable ❌ 无 ❌ 无 ❌ 无 🧊 低

✅ 如何设置隔离级别

查看当前隔离级别:

SELECT @@tx_isolation; -- 旧版本SELECT @@transaction_isolation; -- 新版本

设置当前会话隔离级别:

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

设置全局隔离级别(需重启生效):

SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;

🔍 一图理解隔离级别的三大问题:

问题名称 定义 脏读(Dirty Read) 读取了其他事务未提交的数据 不可重复读(Non-repeatable Read) 同一事务中两次读取同一数据结果不一致(因他人已提交) 幻读(Phantom Read) 同一事务中两次查询多行数据,第二次查询多出“幻影”行(因他人新增或删除了数据)

📊 各隔离级别的行为对比表

隔离级别 脏读 不可重复读 幻读 并发性能 实现方式简述(InnoDB) Read Uncommitted ✅ 可能 ✅ 可能 ✅ 可能 🔥🔥🔥 极高 无锁,几乎不控制并发读写 Read Committed ❌ 避免 ✅ 可能 ✅ 可能 🔥🔥 高 读操作每次获取最新快照 Repeatable Read ❌ 避免 ❌ 避免 ✅ 理论上可能(InnoDB 实际避免) ⚖️ 中 多版本并发控制(MVCC)+ 间隙锁避免幻读 Serializable ❌ 避免 ❌ 避免 ❌ 避免 🧊 极低 每条查询加锁,串行执行事务

🔬 详细解释 + 案例举例:

1️⃣ Read Uncommitted(读取未提交)

  • 脏读:✅
  • 不可重复读:✅
  • 幻读:✅
  • 适用场景:极少用,几乎没有实际业务需求。

🧪 举例

-- 事务 ASTART TRANSACTION;UPDATE accounts SET balance = balance - 100 WHERE id = 1;-- 尚未提交-- 事务 B(此时读取了未提交数据)SELECT balance FROM accounts WHERE id = 1;

2️⃣ Read Committed(读取已提交)

  • 脏读:❌
  • 不可重复读:✅
  • 幻读:✅
  • 适用场景:多数数据库(如 Oracle)默认,业务允许稍微的并发一致性差异。

🧪 举例

-- 事务 ASTART TRANSACTION;SELECT salary FROM employees WHERE id = 5; -- 第一次查询:5000-- 事务 BUPDATE employees SET salary = 6000 WHERE id = 5;COMMIT;-- 事务 A(再次查询:返回6000)SELECT salary FROM employees WHERE id = 5;

3️⃣ Repeatable Read(可重复读,MySQL 默认)

  • 脏读:❌
  • 不可重复读:❌
  • 幻读:✅(InnoDB 实际用“间隙锁”解决)
  • 适用场景:MySQL 默认,兼顾一致性与并发,适合绝大多数场景。

🧪 举例

-- 事务 ASTART TRANSACTION;SELECT * FROM orders WHERE user_id = 10;-- 事务 BINSERT INTO orders (user_id, item) VALUES (10, \'Book\');COMMIT;-- 事务 A(再次查询:依旧没有看到新订单)SELECT * FROM orders WHERE user_id = 10;

InnoDB 用“间隙锁(Gap Lock)”防止插入,避免幻读。


4️⃣ Serializable(可串行化)

  • 脏读:❌
  • 不可重复读:❌
  • 幻读:❌
  • 适用场景:银行、证券类系统,需要极高数据一致性,牺牲并发性能换一致性保障

🧪 机制: 每条查询都加锁(共享锁/排他锁),导致事务基本变成串行执行。


✅ 总结推荐

场景类型 推荐隔离级别 原因 数据一致性优先 Repeatable Read / Serializable 避免读错数据/幻读 并发优先 Read Committed 减少锁冲突、提高吞吐 查询为主、写入较少 Repeatable Read 避免读取旧数据

MySQL 事务隔离级别详解与应用场景分析_mysql事务隔离级别使用场景