MVCC机制

个人理解篇,不一定对,应付面试的时候看的

MVCC(Multi-Version Concurrency Control)全称多版本并发控制,主要用在隔离模式下的提交读、可重复读模式下,依赖于readview和undolog链

一、readview

1、结构

字段

备注

m_ids

活跃事务id集合

min_trx_id

活跃事务id集合中最小事务id

max_trx_id

当前分配给新事务的最大事务id+1

creator_trx_id

生成readview时,当前事务id

2、举例

现在系统中开启了事务A、B、C,对应的trx_id分别是1、2、3

此时有个新事务的读操作时,会产生如下readview

m_ids

1,2,3

min_trx_id

1

max_trx_id

5

creator_trx_id

4

二、undolog链

1、结构

字段

备注

trx_id

事务id

roll_point

上一事务指针,指向上一个undolog节点

key

操作行记录的主键id

type

执行类型(update、insert、delete)

commonvalue

具体的值,没搞清楚具体是什么,但是新值、旧值、更新逻辑应该都有

2、举例

现在系统中开启了事务A、B、C,对应的trx_id分别是1、2、3

此时有个新事务的读操作时,会读取一下undolog链如下

三、操作

1、新事物发起读操作时产生readview,然后从undolog链开始查找并进行如下判断逻辑

if(trx_id == creator_trx_id)访问的是自己的事务,允许访问

if(trx_id < min_trx_id)访问的是已经提交的事务,允许访问

if(trx_id >= max_trx_id)访问的是在生成readview之后的事务,不允许访问

if(min_trx_id <= trx_id < max_trx_id)访问的是活跃中未提交的事务,不允许访问

ps:

1、关于undo链中的举例结构图,其实可以看出,默认在 trx_id=1的条目之前还会有trx_id=0的条目 这个条目是在生成readview时最新的提交数据,在trx_id=3后如果有新事务的话,其实也还有指向trx_id=3的事务,这只是个片段,具体的判断阶段会在这图中这一部分判断的比较集中。

2、关于trx_id=1指向的上一个已提交事务的undolog条目,由mysql来采取一些算法来判断是否存在,一般在被引用的时候都是存在的,不必担心找不到已提交的undolog条目

3、每个undolog条目都是某个表的某一行的数据,如果update修改了10条记录,那么会产生10个undolog条目,同时每个undolog链其实只是某一行的版本变化

四、关于

1、RC和RR区别

mvcc可以在RC(读已提交)和RR(可重复读)中,区别就是RC模式下,每次读都会产生readview,而在可重复读模式下,事务结束之前都是复用事务开始后的第一次读产生的readview

2、RR幻读问题

RR中其实没有完全解决幻读问题,如下场景

2.1表Subject:

场景一:

事务A

事务B

事务B查询结果

start TRANSACTION;

start TRANSACTION;

select * from Subject where difficultly = "困难";

insert into `Subject`(difficultly,type,language) value ('困难','英语','C');

commit;

select * from Subject where difficultly = "困难" for update;

select * from Subject where difficultly = "困难"

可以看到第四步的当前读会出现幻读,而第五步的快照读仍然正常

场景二:

事务A

事务B

事务B查询结果

start TRANSACTION;

start TRANSACTION;

select * from Subject where difficultly = "困难" for update;

insert into `Subject`(difficultly,type,language) value ('困难','英语','C');

commit;

select * from Subject where difficultly = "困难" for update;

select * from Subject where difficultly = "困难"

第三步中事务A在执行插入时会一直无法执行完成,直到事务B中commit后才会执行完成

场景一和场景二区别:

场景一中事务B在事务A插入新数据和提交后执行的当前读,而场景二中事务B在事务A插入新数据和提交前执行的当前读,mysql通过mvcc和临键锁会锁定当前读,这样事务A再插入就插入不了新数据了,就解决了幻读,而场景一是在使用临键锁之前提交的,当前读读的是最新数据,所以会出现幻读

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值