对于mvcc版本控制的解读

1、事务ID生成的时机

begin语句并不生成事务ID,在执行增删改查操作时,才会生成事务ID。

例如:学生表如下

在这里插入图片描述
事务A和事务B分别执行如下语句

AB
begin
begin
update 学生 set 年龄 = 10 where 学号 = ‘S001’
select * from 学生 where 学号 = ‘S001’

查询的结果为如下,年龄并没有被改变,说明A在select的时候才生成事务ID,因为Innodb的mvcc只读取行的系统版本号小于等于当前事务的系统版本号
在这里插入图片描述

2、对mvcc的测试及工作原理分析(基于可重复读)

2、1对mvcc的测试

事务A事务B事务C
beginbeginbeign
update 课程 set 学分 = 1 where 课程号 = ‘C1’
update 学生 set 年龄 = 10 where 学号 = ‘S001’
commit
select * from 学生 where 学号 = ‘S001’
update 学生 set 年龄 = 30 where 学号 = ‘S001’
commit
select * from 学生 where 学号 = ‘S001’

事务C的第一次查询结果
在这里插入图片描述
事务C的第二次查询结果
在这里插入图片描述
2、2工作原理分析(基于update操作和select操作)

事务的更新操作会使得旧的记录以快照的形式存在于undo日志中,就相当于一条记录对应的版本链。
每个数据表都有4个隐藏的列,隐藏主键ID、行版本号、行删除版本号、回滚指针(mvcc只涉及后面3个列)。
read view的格式【当前活跃事务的版本号列表(未提交的事务)】【当前最大事务的版本号(包括提交和未提交的)】

活跃事务最小版本号记为minVersion,当前系统最大版本号记为maxVersion,当前记录版本号为recordVersion。满足以下条件时,该记录才会被查询到。
1、recordVersion < minVersion 或者
2、minVersion <= recordVersion <= maxVersion && recordVersion 不属于 活跃事务版本号列表   
3、在上述两个条件满足之一的情况下,还需要当前行删除版本号大于maxVersion

事务B执行update操作时的undo日志状态
在这里插入图片描述

       事务C执行select语句,生成的read view(其它事务版本可见性视图)为【19】【20】(19为事务A的版本号,20为事务B的版本号)。当前活跃事务的最小版本号minVersion为19,当前事务最大版本号为maxVersion为20。查询到的记录版本号recordVersion为20,因为recordVersion<=maxVersion && recordVersion不在活跃事务版本中 && 当前记录行删除版本号为null,因此读取的记录为10。
事务C执行update操作,并且提交时,undo日志的状态
在这里插入图片描述
       事务C再执行select语句,因为是可重复读,因此read view里保存的依旧是【19】【20】,第一条记录为版本号为19,存在于read view的活跃事务列表中,因此通过回滚指针指向下一条记录。在此处的判断方法和第一次执行select语句相同,因此查询的记录依旧是10。事务后续select延用第一次的select操作的read view,因此有效避免了不可重复读的问题。而rc隔离级别下,每一次的select操作,都会生成一个新的read view,因此第二次读取的记录年龄是30。
2.3 工作原理分析(基于insert)
        insert操作只需要在插入的每一行保存当前系统版本号作为行版本号即可,不会产生undo日志。rr级别下会产生幻读。具体原因还不明白。
2.4 工作原理分析(基于delete)
       delete操作只需要为删除的每一行保存当前系统版本号作为行删除版本号。不产生undo日志(猜测)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值