Mysql MVCC

Mysql MVCC

MVCC Multi Version Concurrency Control ,多版本并发控制。主要为了提高数据库的并发性能。在对同一行数据同时进行读写时,一般会采取加锁的方式来保证一致性,但是这样多个请求会变为串行执行,极大降低Mysql的性能。为此采用MVCC的方式去处理读–写请求,做到在发生读写冲突的时候不用加锁,提高性能。

当前读和快照读

当前读:当前即是最新,顾名思义就是读取的最新版本,因为要读取最新版本,所以在读取的时候,其他事务不能修改,为此需要加锁,当前读常见的SQL如:

  • select … lock in share mode : 共享锁
  • select … for update : 独占锁
  • insert,update,delete : 独占锁

快照读:读取的只是记录行的一个快照,不一定是最新数据。在非串行化的隔离级别中,不加锁的select操作均是快照读。如果是串行化的隔离级别的话,最终会退化为当前读。

MVCC的实现

MVCC多版本并发控制,基于数据版本进行并发访问。MVCC通过为每一个事务分配一个递增的事务id,每个id都会对应一个快照版本,
MVCC需要依靠版本链来实现快照读,在innodb行的内部有两个隐藏列,

  • DB_TRX_ID : 存储插入或者更新语句的最后一个事务的事务ID,6byte
  • DB_ROLL_PTR : 回滚指针,每次对记录进行修改,都会对应undo log,这个指针就会指向之前的undo log通过它可以找到之前的记录。在这里插入图片描述
    innodb的每一行的数据记录除去数据列之外,还额外保留了几个列。

假设有一个当前表中的记录如下所示:
在这里插入图片描述
紧接着,又一个新的事务暂且称为事务1,且该事务的事务id为1,将name修改为tom,此时的数据就成这样的
在这里插入图片描述
然后再有一个事务将age改为30,该事务的事务Id为2,此时的版本链是这样的:
在这里插入图片描述
也就是说,对于记录的每次更新,都会将其旧值链到新纪录的后面,通过回滚指针,链表头的记录就是当前最新的记录。

ReadView

ReadView称为当前事务的读视图,ReadView包含4个内容:

  • m_ids : 生成ReadView时,当前系统中获取的未提交的事务id组成的集合。
  • min_trx_id:m_ids中最小的事务id
  • max_trx_id : mids中最大的事务id+1
  • creator_trx_id:生成该ReadView的事务id

有了这些数据,在RR,RC隔离下,就可以很容易的判断出版本链中的哪条数据可以显示,哪条数据不能显示。只需要从链表头部依次向尾部查询,查询到第一条符合记录的数据返回即可。

1、如果被访问的版本的记录的事务id,等于ReadView中的creator_trx_id,则表明这条记录就是该事物修改的,因此可见。
2、如果被访问的版本的trx_id小于ReadView中的min_trx_id,表示生成该版本的事务在创建ReadView的时候,已经提交了,所以该版本可以读出来。
3、如果被访问版本的记录的事务Id,大于最大的事务id,则说明该记录的事务在之后才产生的,当前不可见。
4、如果被访问的记录介于这个集合中,需要判断是不是和集合中的值相等,如果相等说明当前这个事务还是活跃的,不可见。否则不相等则说明在生成readView的时候,该事务已经被提交了因此可见。

简而言之,对于一个视图的可见不可见总共一下几种情况:

  • 自己修改的,自己可见,不论是否已经提交
  • 版本未提交,不可见
  • 版本已经提交,但是在开启事务视图之后提交的也不见
  • 版本已经提交,且是在事务视图开启之前提交的可见

在RR隔离级别中,仅在第一次执行快照读的时候生成readView,后续都使用该ReadView,但是如果两次快照读之间有当前读则会重新生成ReadView。
在RC隔离级别中,每次都会重新生成ReadView。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值