MySql并发:MVCC+锁

以下基于INNODB引擎,RR隔离级别

MVCC

多版本的并发控制协议

  1. 隐藏列:InnoDB中每行数据都有隐藏列,隐藏列包含了:本行数据的事务id、指向undo log的指针等。
  2. 基于undo log的版本链:每行数据的隐藏列中包含了指向undo log的指针,而每条undo log也会指向更早版本的undo log,形成版本链。
  3. ReadView:通过隐藏列和版本链,Mysql可以将数据恢复到指定版本。具体恢复到哪个由ReadView决定。

所谓ReadView是指事务(A)在某一时刻给整个事务打快照,之后再进行读操作时,会读到事务id和快照比较,从而判断数据对事务A是否可见。


当前读和快照读

  • 当前读

像select lock in share mode(共享锁),for update(排他锁)这些操作都是一种当前读。

读取到得是最新版本,还要保证其他并发事务不能修改当前记录,会对记录加锁。

  • 快照读

不加锁的select操作;前提是隔离级别不是串行级别,快照读基于MVCC

普通select语句

  • RU,不加锁直接读取最新版本,可能出现脏读、不可重复读、幻读
  • RC,不加锁每次执行select都会生成一个readView,避免脏读,会出现不可重复读和幻读
  • RR,不加锁,只有第一次执行select生成一个readView,避免了脏读、不可重复读和幻读
  • 序列化
    • 系统变量autocommit=0时,普通select被转换为select...lock in share mode。也就是S锁;
    • 系统变脸autocommit=1时,普通select不会加锁,只是利用mvcc生成一个readView,因为启动自动提交意味着一个事务只包含一条语句,只执行一条语句不会出现不可重复读和幻读的现象

 

当一个事务(creator_trx_id)对数据进行快照读时:

1、生成当前readview

2、拿到数据的最新事务id:trx_id

3、trx_id = creator_trx_id(当前事务id),说明这条数据是当前事务更新的,可以获取

4、trx_id < min_trx_id,数据在当前所有正在运行事务前更新,可以获取

5、trx_id >= max_trx_id,数据被生成readview之后的事务更改,不能访问

6、生成readview时正在运行的事务列表包含trx_id,数据是被当前列表的事务更新,通过undolog找到记录的上一个事务id,回到步骤2

7、trx_list不包含trx_id,可以访问(假设当前事务id = 10,比如id = 14 和 id = 15事务,在生成readview前id = 14 事务提交,导致一系列条件不符合,也不在trx_id中,建立readview后读取的是最新id = 14的记录)

8、结束

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值