MVCC多版本并发控制

1.MVCC的意义

锁的意义在于并发操作数据时,权限的控制
例如: 一行记录在有一个client访问时加锁,其他客户端能否操作,能进行怎么操作的权限控制
​
MVCC的意义在于并发操作数据时,能获取到什么样数据的控制
例如: 可重复读情况下,其他client修改以后,能否获取到最新数据的
​
这两个一个是控制能否操作,一个是控制操作以后什么结果,mvcc主要是针对select …from…普通查询数据结果的控制
select …from…这种普通查询语句是不会收到锁的影响的,都可以执行成功

2.ReadView

事务id生成: 在一个事务开启后,执行begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个修改操作InnoDB表的语句,事务才真正启动,才会向mysql申请事务id,mysql内部是严格按照事务的启动顺序来分配事务id的。
当一个select查询语句执行时,会生成一个ReadView 
ReadView: 所有未提交的事务数组(其中数组最小的作为min_id) + 已经创建的最大事务(作为max_id)
​
然后ReadView会被划分成三个区间 
    1. 小于mid_id的为一定提交的事务
    2. 大于max_id的为一定没有开启的事务
    3. 中间位置为  可能提交也可能没提交的事务
    ~~min_id)    [min_id,max_id]    (max_id~~
RR隔离级别:
    ReadView只会在第一次查询生成,只要事务没有提交,一直都是这个ReadView,所以可重复读,并且读到数据一致
    但是如果在事务中,有读有写,ReadView就会被清除,再读会生成新的ReadView
        结合我们之前的锁,如果写,那么同一时刻一定不能有其他写的事务,会发生排他锁,那么再次读读到我们刚才写的新数据不也是一个应该的操作吗,数据库这种设计是非常指挥并且贴合我们的使用场景的
        
RC隔离级别:
    ReadView每次查询都会生成

3.三个隐藏字段

每行记录除了我们自定义的字段外,还有数据库隐式定义的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段
•       DB_TRX_ID
•       6字节,最近修改事务id,记录创建这条记录或者最后一次修改该记录的事务id
​
•       DB_ROLL_PTR
•       7字节,回滚指针,指向这条记录的上一个版本,用于配合undolog,指向上一个旧版本
​
•       DB_ROW_JD
•       6字节,隐藏的主键,如果数据表没有主键,那么innodb会自动生成一个6字节的row_id
我们知道UndoLog用于存储老版本的数据,那么UndoLog是一个大文件,里面一定有很多行的数据,如果我们要查询某一行的数据,一定是先去硬盘查找这行数据,再通过DB_ROLL_PTR字段去查找指向的老版本记录比对
​
DB_ROLL_PTR:
如果没有隐性字段,复杂度将非常的高
    1. 更新数据,没有这个指针,要遍历UndoLog,找到当前行数据,将老版本数据添加到UndoLog版本链上,如果更新10,100,1000行呢,查找过程将非常费事
    2. 回滚数据,没有这个指针,同样的遍历UndoLog,并且还要进行比对是不是当前这行记录的,如果两个记录的老版本相同的?
    那你这个老版本会找错呀
基于这两个原因,行记录是一定要有指针指向UndoLog的,查找Undolog可以复用查找行的索引,还能保证查找到记录的正确性
​
DB_TRX_ID:
   这个隐性字段的存在也是必要的,在数据更新时,直接将老版本放到UndoLog上,如果没有DB_TRX_ID,你如果不在进行写时加上事务id,你能知道上一个事务id是啥了吗   比如,现在记录是1,你想更新到2,1就会被作为老版本,那么你存放到Undolog中,老版本id是啥鬼知道

4.UndoLog

一个被行记录指针指向的老版本链,新记录会将原来的行记录挤到版本链中

5.版本比对规则

1. 如果 row 的 trx_id 落在绿色部分( trx_id<min_id ),表示这个版本是已提交的事务生成的,这个数据是可见的;
2. 如果 row 的 trx_id 落在红色部分( trx_id>max_id ),表示这个版本是由将来启动的事务生成的,是不可见的(若 row 的 trx_id 就是当前自己的事务是可见的);
3. 如果 row 的 trx_id 落在黄色部分(min_id <=trx_id<= max_id),那就包括两种情况
    a. 若 row 的 trx_id 在视图数组中,表示这个版本是由还没提交的事务生成的,不可见(若 row 的 trx_id 就是当前自己的事务是可见的);
    b. 若 row 的 trx_id 不在视图数组中,表示这个版本是已经提交了的事务生成的,可见。
    视图数组:  记录未提交的数组记录
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值