ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

笔记:MVCC的理解

2021-05-23 12:32:09  阅读:169  来源: 互联网

标签:事务 log undo 理解 笔记 提交 MVCC 版本 id


MVCC介绍

MVCC其实就是多版本并发控制,用来解决幻读问题,同时解决幻读问题还有间隙锁。

UNDO LOG

undo log是用来事务回滚的,具体细节回看undo log文章

这里要注意的一点是,每条undo log就是一个表的版本

undo log又分为两种

  • Insert undo log:针对Insert操作的
  • Update undo log:针对update和delete操作的

update操作又分为两种,一种是更新主键,一种是不更新主键

  • 更新主键:先新增后标记删除旧记录(产生Insert undo log和update undo log)
  • 不更新主键:单纯产生一个新版本的update undo log

MVCC原理

每个事务执行一条更新操作语句(DML语句)才会生成自己的事务Id

而每个事务执行一条查询语句就会获得一个一致性视图read-view,以后的查询都会基于这个去查询

read-view

read-view是由所有未提交事务id数组和已提交最大事务id所组成

[100,200,300] 400 //数组里面的是未提交事务id,旁边的是已提交最大事务id

那么根据read-view就可以将所有事务划分为3部分

  • 已提交
  • 未提交与已提交
  • 未提交

在这里插入图片描述
那么这三部分是如何区分的呢?

我们将read-view维护的未提交数组称为活跃区,在这个活跃区里面,最小的事务id称为min_id,最大的称为max_id

在活跃区以外的事务id,要么是未开始,要么是已经提交的。由于事务id是有序创建的,所以小于min_id的事务一定是已经提交的,所以已提交的区域就是小于min_id的,然后,未提交与已提交的区域就是由read-view维护的活跃区和最大已提交的事务id组成(活跃区为未提交,max_id到已提交最大事务id的区间一定是已提交【道理与小于min_id一样】),大于最大已提交的事务id肯定都是未开始的,所以归为未提交区域。

这里再对max_id到最大已提交事务id区间进行说明,要分两种情况讨论

  • max_id小于最大已提交事务id,那么max_id到最大已提交事务id区间内的事务一定是已提交的
  • max_id大于最大已提交事务id,那么区间里面,不一定都是已提交的,区间里面的事务id如果出现在活跃区,就是未提交的,如果不在活跃区出现就是已提交的

版本链

版本链是由undo log形成的,undo log是一个表数据里面的一个历史版本(每条行记录都有自己的版本链),并发的事务可能会由于查询同一条行记录,那么获取的版本链是一样的(全局使用),当事务进行DML操作时,对应的行就会生成对应的undo log(新的版本),在undo log里面标上自己的事务id,让后使用指针(row_pointer)来关联上之前的undo log,那么undo log就会形成一个链表,称为版本链(新版本的会在链表前面,每条行记录会有两个隐藏字段,一个是trx_id,也就是事务id,另一个是row_pointer指向上一个undo log版本)

在这里插入图片描述

实现

现在事务开始进行查数据(Select),根据read-view维护的活跃区和最大已提交事务id

查数据的时候,就是根据undo log的版本链进行匹配,匹配的规则(再提一下,每个undo log就是一个行记录的版本,所以查的行数据其实就是一个undo log)

  • 事务id小于min_id是已提交的,可见,直接返回undo log
  • 事务id在活跃区的,不可见,通过链表找下一条undo log
  • 事务id大于max_id,同理按照前面所提到的规则去判断是否已提交,提交就是可见,直接返回undo log,未提交就是不可见,通过链表找下一条undo log
  • 事务id大于已提交最大事务id:是不可见的,通过链表找下一条undo log

经过这样去匹配,就可以找到对应自己版本的undo log

注意,上述的规则对于可重复读和读已提交都是一样的

可重复读与读已提交的区别

  • 可重复读:每次读的快照都是同一个undo log
  • 读已提交:每次读的快照都是最新的undo log

这两者底层实现的区别,其实就是read-view的维护,可重复读,一旦执行了SELECT语句之后,read-view不会再改变,但读已提交,每次的SELECT都会去更新read-view

补充:Insert undo log

Insert update log对于当前事务来说必定是可见的,因为是自己操作的,但对于其他事务来说,必定是不可见的,因为还没有事务提交,所以Insert update log在事务提交的时候就会被删除

Insert undo log并不会形成版本链,因为插入嘛,肯定是新数据,所以新生成的行数据会表上插入的事务id,不影响前面提到的版本链匹配。

标签:事务,log,undo,理解,笔记,提交,MVCC,版本,id
来源: https://blog.csdn.net/GDUT_Trim/article/details/117190793

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有