MySQL事务隔离级别

2025-07-23 技术笔记 1

概念

MySQL事务隔离级别是为了解决并发事务互相干扰的问题。MySQL有四种隔离级别:

  • 未提交读 READ UNCOMMITTED
  • 已提交读 READ COMMITTED
  • 可重复读 REPEATABLE READ
  • 序列化 SERIALIZABLE

四种隔离级别

未提交读

事务能够读到其他事务未提交的数据,未提交的数据可能会回滚,这个级别读到的数据是脏数据,这个问题成为脏读。

已提交读

事物能读取到已经提交事物的数据,不会有脏读问题。但是在同一个事务内,多次读取同一条数据,由于其他事务的修改,导致前后读取的结果不一致,叫做不可重复读。

可重复读

MySQL的默认隔离级别,可以解决不可重复读问题。但是不能解决幻读问题,幻读是两次查到的数据数量不一致,不可重复读是同一条数据内容不同,幻读是返回的数据添加或删除了数量。

MySQL的InnoDB默认使用多版本并发控制(MVCC,Multi-Version Concurrency Control)实现可重复读。

  1. 数据库为每个事务维护一个数据快照。
  2. 事务读取的是事务开始时数据的快照版本。
  3. 即使其他事务修改了数据,当前事务看到的仍然是它开始的一致视图
  4. 因为只是对已经存在的数据进行版本快照,新插入的无法提供历史版本,所以导致了幻读。
  5. MySQL的InnoDB引擎在可重复读隔离级别下通过间隙锁(Gap Lock)和next-key锁额外解决幻读问题。这与SQL规范不同

序列化

事务最高隔离级别,强制事务排序,使其不会发生冲突,解决了脏读、不可重复读和幻读问题,但是执行效率低,真正使用场景不多。

并发事务中的问题

脏读

一个事务读取到另一个事务未提交的数据。

不可重复读

一个事务读取同一条记录两次,得到结果不一致(重点在update和delete),其他事务对数据进行了修改。

幻读

一个事务读取两次,得到的记录条数不一致(重点在insert)。其他事务插入了数据。

关系总结

隔离级别 脏读 不可重复读 幻读
未提交读 可能 可能 可能
已提交读 不可能 可能 可能
可重复读 不可能 不可能 可能
序列化 不可能 不可能 不可能

*注:MySQL InnoDB在REPEATABLE READ下实际防止了幻读

具体使用

查看当前隔离级别

-- 查看全局隔离级别 
SELECT @@global.transaction_isolation; 
-- 查看当前会话隔离级别 
SELECT @@transaction_isolation;

更新隔离级别

-- 更新全局
SET GLOBAL TRANSACTION ISOLATION LEVEL level;
-- 更新当前会话
SET SESSION TRANSACTION ISOLATION LEVEL level;

可用的隔离级别有

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE

演示脏读

步骤 事务1 事务2 备注
1 set session transaction isolation level read uncommitted; 将隔离级别设置成未提交读
2 start transaction; start transaction;
3 select * from students; 此时无数据
4 insert into students values (null,'xieyanjun');
5 select * from students; 事务1可读取到事务2插入的数据
6 rollback; 事务2将数据回滚
7 select * from students; 无数据

演示不可重复读

步骤 事务1 事务2 备注
1 set session transaction isolation level read committed; 将隔离级别设置成已提交读
2 insert into students values (null,'xieyanjun'); 初始化数据
3 start transaction;
4 select * from students where id = 1; xieyanjun
5 start transaction;
6 update students set name = 'xieyanjun1' where id = 1;
7 commit; 事务2将数据更新并提交
8 select * from students where id = 1; xieyanjun1

演示幻读

MySQL的InnoDB引擎在REPEATABLE READ隔离级别上通过间隙锁(Gap Lock)额外防止了幻读。所以这里无法演示,理论上在标准SQL下,事务一查询出一条数据,当事务二插入数据并提交后,事务一再次查询时会有两条数据,两次查询出结果数量不一致,出现幻读。

相关文章

快慢指针简单用法

快慢指针简单用法

如何避免愚蠢的见识

罗素关于如何避免有愚蠢的见识这种行为所需要的原则

Markdown 格式示例文章

Markdown 格式示例文章