InnoDB MVCC基本原理

一、实现原理

1、每一行记录都有2个隐藏列:

  • DATA_TRX_ID 记录最近更新的这条记录的事务ID
  • DATA_ROLL_PTR 表示指向该行回滚段的指针,通过这个指针找到修改记录的那行数据的旧版本。

2、过程

  • 插入时将行记录拷贝到undo段中,DATA_TRX_ID指向这个事务的ID,DATA_ROLL_PTR都不动,因为此时只有最新的一个版本,没有其他版本
  • 此时更新这行数据,那么DATA_TRX_ID就会指向修改记录的这个事务ID,并且DATA_ROLL_PTR会指向undo log段中刚刚拷贝过来的旧版本记录。
  • 如果有多次更新,那么undo log会组成一个链表,里面存储数据的各个版本记录

 

二、如何实现一致性读 --- ReadView

ReadView是用来判断历史事务链表的记录中,哪些事务可以被当前事务可见。

通过select语句来创建ReadView

1、主要包含以下4个部分:

  • m_ids:表示生成ReadView时当前系统中活跃的读写事务id列表,这些事务是没有commit的事务
  • min_trx_id:上面m_ids中最小的那个事务
  • max_trx_id:readview中应该分配给下一个事务的id值,即这个值不在m_ids中
  • creator_trx_id:表示生成该ReadView事务的事务Id

2、ReadView如何判断版本链中哪个版本可用

(1)、trx_id = creator_trx_id时,表示这个事务就是由本身创建的,那当然可见。

(2)、trx_id < min_trx_id,min_trx_id是当前没提交的那些事务中最小的那个,小于这个值,代表这个事务已经提交了,所以可以访问到。

(3)、trx_id > max_trx_id 那这个事务肯定没提交,访问不到。

(4)、min_trx_id <= trx_id <=max_trx_id 如果这个trx_id在m_ids中,那么就访问不到,因为m_ids里是还没有提交的事务,如果在这个区间,但是不在m_ids中,那就证明这个事务提交了,所以可以访问到。例如:

m_ids={1,2,4,5} trx_id=3

这时1,2,4,5都是没有提交的,所以访问不到,但是3不在这里面,但又在这个区间里,3就是提交了的,可以访问到。

3、读未提交(RU)直接读取最新的记录即可,串行化(SERIALIZABLE)需要加互斥锁来访问,因此不需要MVCC的帮忙

4、读已提交(RC)的情况下,每一次select时,都会将当前活跃的事务的加入到ReadView中,都会生成一个新的ReadView。

而可重复读(RP)的情况下,第一次查询时会将活跃的事务加入到ReadView中,只会生成一个ReadView,之后每次查询都是沿用这个ReadView。

三、当前读和快照读

1、 select...lock in share mode (共享读锁)

  select...for update

  update , delete , insert

  当前读, 读取的是最新版本, 并且对读取的记录加锁, 阻塞其他事务同时改动相同记录,避免出现安全问题。

2、快照读就是利用mvcc来读

3、快照读是利用mvcc来实现可重复读的(解决幻读),而当前读,是根据next-key锁来实现的。

一个事务中,第一次执行select..for update,之后另一个线程插入了一条,第一条没有提交时,后面的插入操作一直处于阻塞状态,第一条提交之后,第二条才可以插入。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ccu78150581

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值