一、前言
本文围绕这三个话题展开学习 RR
如何解决幻读?
MVCC
原理- 实验:
RR
与 幻读 - 案例:死锁
先来回顾下 MySQL
中 InnoDB
支持的四种事务隔离 和 并发事务所带来的一些问题:
- 读未提交:能读到一个事务的中间过程,违背了
ACID
特性,存在脏读的问题,基本不会用到。 - 读提交:表示如果其他事务已经提交,那么就可以看到。在生产环境中用的并不多。
- 可重复读:默认级别,使用最多的一种。其特点是有
Gap
锁(间隙锁)。 - 可串行化:所有的实现都是通过锁来实现的。
并发事务处理也会带来一些问题:脏读、不可重复读、幻读
-
脏读:一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态。
-
不可重复读:一个事务按相同查询条件前后两次读取,读出的数据不一致(修改、删除)。
-
幻读:一个事务内按相同的查询条件重新查询数据,却发现其他事务插入了满足其查询条件的新数据。
本文脉络梳理: RR
为了更快并发,引入 MVCC
,但有幻读的可能,为解决幻读,引入 Gap
锁,Gap
可能造成死锁。
二、MVCC
原理
MVCC
(多版本控制): 指数据库中为了实现高并发的数据访问,对数据进行多版本处理,并通过事务的可见性来保证事务能看到自己应该看到的数据版本。
MVCC
最大的好处是读不加锁,读写不冲突。- 在
OLTP (On-Line Transaction Processing)
应用中,读写不冲突很重要,几乎所有RDBMS
都支持MVCC
。
注意:MVCC
只在 读提交RC
和 可重复读RR
两种隔离级别下工作。 注意:MVCC
只在 读提交RC
和 可重复读RR
两种隔离级别下工作。 注意:MVCC
只在 读提交RC
和 可重复读RR
两种隔离级别下工作。
(1)MVCC
多版本实现
MySQL
实现 MVCC
机制的时候,是基于 undo log
多版本链条 + ReadView
机制。
undo log
多版本链: 每一次对数据库的修改,都会在undo log
日志中记录当前修改记录的事务号及修改前数据状态的存储地址(即ROLL_PTR
),以便在必要的时候可以回滚到老的数据版本。ReadView
机制: 在多版链的基础上,控制事务读取的可见性。(主要区别是:RC<