Mysql之MVCC

基础概念:

MVCC:全称为Multi-Version Concurrency Control,即多版本并发控制,是基于数据版本对并发事务进行访问。

当前读:像select in share mode, select for update, update, insert, delete这些操作都是当前读,就是读取的记录是最新的版本。读取时还要保证其它事务不能修改当前记录,会对该记录加锁。

快照读:就是普通的select操作SQL语句,不会对记录加锁。快照读的前提是隔离级别不能是串行级别,否则会退化成当前读。

ReadView:是快照读SQL执行时MVCC提取数据的依据。它是一个数据结构,包含四个字段:

m_ids:当前活跃的事务编号集合

min_trx_id:最小的活跃事务编号

max_trx_id:预分配的事务编号,即当前最大事务编号+1

creator_trx_id:ReadView创建者的事务编号

MVCC的实现原理:

MVCC的实现要基于undolog(回滚日志)版本链和ReadView以及记录中的三个隐藏字段。

三个隐藏字段:

db_trx_id:最近修改事务的id,记录创建这条记录或者最后一次修改这条记录的事务id。占6个字节

db_roll_ptr:回滚指针,指向这条记录的上一个版本,用于配合undolog。占用7个字节。

db_row_id:隐藏的主键,如果表中没有主键,innodb会自动生成一个6字节的row_id.

(其实,还有一个隐藏字段,删除标记) 

RC(读已提交)隔离级别下:在每一次快照读时,都会生成一个全新的ReadView

RR(可重复读)隔离级别下:连续多次快照读时只在第一次快照读时,都会生成ReadView 

若一条记录经历了以下过程

 

 那么此时生成undolog版本链则是以下这样:

 undolog版本链使用规则:

沿着版本链依次判断:

1、当前版本链事务id(trx_id)是否等于creator_trx_id,若相等则说明读取操作的事务与最近修改的事务为同一事务,此时肯定可以访问的。

2、判断trx_id 是否小于min_trx_id,若小于,则说明该事务已经提交,可以访问。

3、判断trx_id 是否大于max_trx_id,若大于,则说明该事务是在ReadView生成后才开启的,则不允许访问。

4、判断 min_trx_id <= trx_id <= max_trx_id 是否成立,若成立则判断该事务id是否在当前活跃的事务编号集合(m_ids)中,若不存在则说明是已提交事务,则允许访问,否则不允许访问。

下面将上例带入规则

RC隔离级别下:

第一次Select 查询生成的

ReadView:m_idx={2,3,4}, max_trx_id=5,min_trx_id=2,cretor_trx_id=4

带入版本链:

(1.1) trx_id(3)不等于cretor_trx_id(4),不允许访问。

(1.2) trx_id(3)不小于min_trx_id(2),不允许访问。

(1.3) trx_id(3)不大于max_trx_id(5),不允许访问。

(1.4) min_trx_id(2) <= trx_id(3) <= max_trx_id(5) 成立,但在活跃事务编号集合中,则不允许访问

【其实,此时事务3的执行操作还未开始,并不存在于版本链中,大家理解即可】

-----------------------------------------------------------------------------------------------------------------------

(2.1) trx_id(2)不等于cretor_trx_id(4),不允许访问。

(2.2) trx_id(2)不小于min_trx_id(2),不允许访问。

(2.3) trx_id(2)不大于max_trx_id(5),不允许访问。

(2.4) min_trx_id(2) <= trx_id(2) <= max_trx_id(5) 成立,但在活跃事务编号集合中,则不允许访问

-----------------------------------------------------------------------------------------------------------------------

(3.1) trx_id(1)不等于cretor_trx_id(4),不允许访问。

(3.2) trx_id(1)不小于min_trx_id(2),不允许访问。

(3.3) trx_id(1)不大于max_trx_id(5),不允许访问。

(3.4) min_trx_id(2) <= trx_id(1) <= max_trx_id(5) 成立,但不在活跃事务编号集合中,则允许访问

故第一次select 结果是name为张三的记录。

第二次select生成的ReadView:

ReadView:m_idx={3,4}, max_trx_id=5,min_trx_id=3,cretor_trx_id=4

带入版本链可得结果是name为李四的记录。

RR隔离级别下:

同理可知,两次查询结果均是name为张三的记录。

备注:第一次查询时,事务3还没执行,故在版本链中是存在。本着省事的原则就不再画了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值