news 2026/4/2 2:11:55

MySQL,InnoDB究竟如何巧妙实现,4种事务的隔离级别(第9讲,超硬核)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL,InnoDB究竟如何巧妙实现,4种事务的隔离级别(第9讲,超硬核)

《数据库架构100讲》

9. InnoDB四种隔离级别

事务ACID特性,其中I代表隔离性(Isolation)。

什么是事务的隔离性?

隔离性是指,多个用户的并发事务访问同一个数据库时,一个用户的事务不应该被其他用户的事务干扰,多个并发事务之间要相互隔离。

一个事务怎么会干扰其他事务呢?

咱们举例子来说明,假设有InnoDB表:

t(id PK, name);

表中有三条记录:

1, shenjian

2, zhangsan

3, lisi

case 1:读脏

事务A,先执行,处于未提交的状态:

insert into t values(4, wangwu);

事务B,后执行,也未提交:

select * from t;

如果事务B能够读取到(4, wangwu)这条记录,事务A就对事务B产生了影响,这个影响叫做“读脏”,读到了未提交事务操作的记录。

case 2:不可重复读

事务A,先执行:

select * from t where id=1;

结果集为:

1, shenjian

事务B,后执行,并且提交:

update t set name=xxoo where id=1;

commit;

事务A,再次执行相同的查询:

select * from t where id=1;

结果集为:

1, xxoo

这次是已提交事务B对事务A产生的影响,这个影响叫做“不可重复读”,一个事务内相同的查询,得到了不同的结果。

case 3:幻读

事务A,先执行:

select * from t where id>3;

结果集为:

NULL

事务B,后执行,并且提交:

insert into t values(4, wangwu);

commit;

事务A,首次查询了id>3的结果为NULL,于是想插入一条为4的记录:

insert into t values(4, xxoo);

结果集为:

Error : duplicate key!

事务A的内心OS是:你TM在逗我,查了id>3为空集,insert id=4告诉我PK冲突?

这次是已提交事务B对事务A产生的影响,这个影响叫做“幻读”。

可以看到,并发的事务可能导致其他事务:

(1)读脏;

(2)不可重复读;

(3)幻读;

InnoDB实现了哪几种事务的隔离级别?

按照SQL92标准,InnoDB实现了四种不同事务的隔离级别:

1. 读未提交(Read Uncommitted);

2. 读提交(Read Committed, RC);

3. 可重复读(Repeated Read, RR);

4. 串行化(Serializable);

不同事务的隔离级别,实际上是一致性与并发性的一个权衡与折衷。

InnoDB的四种事务的隔离级别,分别是怎么实现的?

InnoDB使用不同的锁策略(Locking Strategy)来实现不同的隔离级别。

一,读未提交(Read Uncommitted)

这种事务隔离级别下,select语句不加锁。

画外音:官方的说法是

SELECT statements are performed in a nonlocking fashion.

此时,可能读取到不一致的数据,即“读脏”。这是并发最高,一致性最差的隔离级别。

二,串行化(Serializable)

这种事务的隔离级别下,所有select语句都会被隐式的转化为select ... in share mode.

这可能导致,如果有未提交的事务正在修改某些行,所有读取这些行的select都会被阻塞住。

画外音:官方的说法是

To force a plain SELECT to block if other transactions have modified the selected rows.

这是一致性最好的,但并发性最差的隔离级别。

在互联网大数据量,高并发量的场景下,几乎不会使用上述两种隔离级别。

三,可重复读(Repeated Read, RR)

这是InnoDB默认的隔离级别,在RR下:

1. 普通的select使用快照读(snapshot read),这是一种不加锁的一致性读(Consistent Nonlocking Read),底层使用MVCC来实现,具体的原理在《InnoDB的高并发是因为MVCC(第5讲)》中有详细的描述;

2. 加锁的select(select ... in share mode / select ... for update), update, delete等语句,它们的锁,依赖于它们是否在唯一索引(unique index)上使用了唯一的查询条件(unique search condition),或者范围查询条件(range-type search condition):

- 在唯一索引上使用唯一的查询条件,会使用记录锁(record lock),而不会封锁记录之间的间隔,即不会使用间隙锁(gap lock)与临键锁(next-key lock)

- 范围查询条件,会使用间隙锁与临键锁,锁住索引记录之间的范围,避免范围间插入记录,以避免产生幻影行记录,尽量避免不可重复的读

画外音:这一段有点绕,多读几遍。

关于记录锁,间隙锁,临键锁的更多说明,详见《MySQL,InnoDB的select为什么会阻塞insert?(第8讲)》。

四,读提交(Read Committed, RC)

这是互联网最常用的隔离级别,在RC下:

1. 普通读是快照读;

2. 加锁的select, update, delete等语句,除了在外键约束检查(foreign-key constraint checking)以及重复键检查(duplicate-key checking)时会封锁区间,其他时刻都只使用记录锁;

此时,其他事务的插入依然可以执行,就可能导致,读取到幻影记录。

总结

1. 并发事务之间相互干扰,可能导致事务出现读脏,不可重复度,幻读等问题;

2. InnoDB实现了SQL92标准中的四种隔离级别;

- 读未提交:select不加锁,可能出现读脏;

- 读提交(RC):普通select快照读,锁select /update /delete 会使用记录锁,可能出现不可重复读;

- 可重复读(RR):普通select快照读,锁select /update /delete 根据查询条件情况,会选择记录锁,或者间隙锁/临键锁,以防止读取到幻影记录;

- 串行化:select隐式转化为select ... in share mode,会被update与delete互斥;

3. InnoDB默认的隔离级别是RR,用得最多的隔离级别是RC;

知其然,知其所以然。

思路比结论更重要。

==全文完==

有架构合集吗?

《流量从10万到10亿,80个架构问题》

《关于即时通讯架构的一切!》

Q4内测了一个新产品,看普通人起号能否复制:

《复盘来了,4周,人均41W+》

内测成绩不错,4周的时间人群你全网流量41W+,1月份启动二期,点击阅读原文一起参与!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/25 18:49:12

手把手LVGL教程:在STM32上实现LCD显示的全过程

手把手教你用LVGL在STM32上点亮LCD:从零开始的嵌入式GUI实战 你有没有遇到过这样的场景?项目需要一个带触摸屏的HMI界面,老板说“别搞Linux,成本太高”,同事说“emWin要授权费,TouchGFX又太吃资源”……这时…

作者头像 李华
网站建设 2026/3/18 0:33:35

IAR版本兼容性说明:不同芯片适配要点

IAR版本兼容性实战指南:从旧项目迁移看芯片适配的那些坑你有没有遇到过这样的场景?一个原本在IAR 8.30上跑得好好的STM32F4电机控制工程,拿到新板子STM32G474上一编译——直接报错“Device not supported”;或者升级到最新版IAR后…

作者头像 李华
网站建设 2026/4/1 22:36:34

一文说清LTspice电路仿真时域分析核心要点

深入LTspice时域仿真:从原理到实战的完整指南在电子设计领域,一个再熟悉不过的场景是:你花了几周时间画好PCB、焊完板子,通电瞬间却发现输出电压震荡不止,或者负载一跳变就掉压。拆焊、改电路、再制板……一轮下来时间…

作者头像 李华
网站建设 2026/4/1 1:45:01

完整指南:AUTOSAR架构图配置工具链使用

从零构建汽车电子系统:AUTOSAR架构图与配置工具链实战指南你有没有遇到过这样的场景?一个ECU项目刚进入集成阶段,不同团队交付的模块却因为信号命名不一致、数据类型错位、通信时序冲突而无法对接。调试数周后才发现,问题根源竟是…

作者头像 李华
网站建设 2026/3/31 21:30:31

xTaskCreate与外设驱动集成:从零实现

从裸机到多任务:用xTaskCreate构建真正“活着”的嵌入式系统你有没有遇到过这样的场景?一个简单的温湿度采集项目,开始只是轮询读一下传感器、点个灯、串口打个日志。后来加了 LoRa 发送,再后来要支持远程配置命令,还要…

作者头像 李华
网站建设 2026/4/1 22:50:00

Arduino安装驱动手动加载步骤:项目应用实例

Arduino驱动安装实战:从手动加载到工业传感器采集的完整链路打通 你有没有遇到过这样的场景? 新买的Arduino开发板插上电脑,IDE里却死活找不到端口;设备管理器里躺着一个带黄色感叹号的“未知USB设备”;点击上传代码…

作者头像 李华