更多特训营笔记详见个人主页【面试鸭特训营】专栏
241230
1. MySQL 中的事务隔离级别有哪些?
常见并发问题
| 名称 | 含义 |
|---|---|
| 脏写 | 一个事务修改了另一个未提交事务的数据 |
| 脏读 | 一个事务读取了另一个未提交事务修改的数据 |
| 重复读 | 一个事务多次读取同一数据时,由于其他事务的修改,返回了不同的结果 |
| 幻读 | 一个事务前后两次在进行范围查询时,由于另一个事务的插入操作,导致前后读取不一致 |
读未提交
- 一个事务可以看到其他事务未提交的数据修改
- 可能会导致脏读,即读取到其他事务未提交的数据
读已提交
- 一个事务只能看到其他事务已提交的数据修改
- 可以避免脏读
- 可能会导致不可重复读,即在同一个事务中,前后两次相同的查询方案可能会返回不同的查询结果
可重复读(MySQL 默认的隔离级别)
- 可以确保一个事务中的多次执行相同的查询方案返回的结果是一致的
- 可以避免不可重复读
- 可能会导致幻读,即在同一个事务中,多次范围查询可能会返回不同数量的数据行
串行化(序列化)
- 所有事务串行执行
- 可以避免所有的并发问题,但是会导致性能大大降低
效率对比
- 并发性:读未提交 > 读已提交 > 可重复读 > 串行化
- 数据一致性:读未提交 < 读已提交 < 可重复读 < 串行化
- 一般互联网大厂会选择 读已提交 隔离级别
表格汇总
√为已解决,×为未解决
| 隔离级别 | 含义 | 脏写 | 脏读 | 重复读 | 幻读 |
|---|---|---|---|---|---|
| 未提交读 | 可读取其他事物未提交的结果 | √ | × | × | × |
| 已提交读 | 在事务开始时,只能读取其他事务已经提交的数据 | √ | √ | × | × |
| 可重复读 | 事务在读取数据时会将其锁定,防止其他事务修改 | √ | √ | √ | × |
| 可序列化 | 所有事务之间串行执行 | √ | √ | √ | √ |
2. MySQL 默认的事务隔离级别是什么?为什么选择这个级别?
- MySQL 默认的事务隔离级别时可重复读度(Repeatable Read),即RR
- 为了兼容早期 binlog 和 statement 格式问题,选择可重复读作为默认隔离级别
- 如果使用读未提交、读已提交,使用 statement 格式的 binlog 会导致主从数据库数据不一致
3. 数据库的脏读、不可重复度和幻读分别是什么?
脏读
- 一个事务读取到了另一个事务未提交的数据信息。
- 如果该未提交事务最终被回滚,那么第一个事务读取的数据就是不一致的(脏的)
- 举例说明
- 现有共享变量
money,初始值为 100 - 事务 A 将
money修改为 200,还未提交时,事务 B 读取到了money = 200的信息 - 最终事务 A 未提交且被回滚了,导致事务 A 对
money的修改没有进行提交,money实际上还是 100 - 但是事务 B 已经读取到了
money = 200的信息,200 就是脏数据,事务 B 的这次读取就是脏读
- 现有共享变量
不可重复度
- 在同一事务中,读取同一个数据两次,但由于其他事物的提交,两次读取的结果不同
- 举例说明
- 现有共享变量
money,初始值为 100 - 事务 A 第一次读取时,读到了
money = 100的信息 - 事务 B 将
money修改为 200,并提交修改操作 - 事务 A 第二次读取时,读到了
money = 200的信息,与第一次读取时的值不同
- 现有共享变量
幻读
- 在同一个事务中,执行相同的查询操作,返回的结果集由于其他事务的插入而发生变化
- 举例说明
- 现有共享变量
money,初始值为 100 - 事务 A 第一次查询满足
money < 500条件的记录,得到一条记录 - 事务 B 插入了一条
money2 = 200的记录 - 事务 A 第二次查询满足
money < 500条件的记录,得到两条记录,看到了第一次查询时没看到的记录money2 = 200
- 现有共享变量
不可重复读和幻读的区别
- 不可重复度是针对单独的某一条数据,两次读取时数据的内容不一致
- 幻读是针对数据的总数量,两次读取时数据总量不一致
表格汇总
| 名称 | 含义 |
|---|---|
| 脏写 | 一个事务修改了另一个未提交事务的数据 |
| 脏读 | 一个事务读取了另一个未提交事务修改的数据 |
| 重复读 | 一个事务多次读取同一数据时,由于其他事务的修改,返回了不同的结果 |
| 幻读 | 一个事务前后两次在进行范围查询时,由于另一个事务的插入操作,导致前后读取不一致 |
1431

被折叠的 条评论
为什么被折叠?



