MVCC、事务和锁的神奇组合

从一个问题开始

前提:在可重复读事务隔离级别下,事务的开始都是从开始执行sql开始的。一般的begin/start transaction并不能立刻开启事务。

我们可以使用 start transaction with consistent snapshot;来立刻开启一个事务。

现在有表和数据:

CREATE TABLE `t` (`id` int(11) NOT NULL,`k` int(11) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB; 
insert into t(id, k) values(1,1),(2,2);

sessionA

sessionB

sessionC

start transaction with consistent snapshot;

start transaction with consistent snapshot;

update t set k = k+1 where id=1;

update t set k = k+1 where id=1;

select * from t where id =1;

select * from t where id=1;

commit;

空位C

commit;

sessionC没有显示开启事务,说明它本身就是一个事务。更新完后自动提交。

结果:sessionA查到k的结果为:1,sessionB查到k的结果为3.

sessionA很好解释,可重复读下,开启事务查到的结果是一致的,所以结果是1。Mysql是是如何实现的呢?

这要说到Mysql的视图分为2种,一种是view,是一个虚拟表,真是存在,可以当做表查询;另一种就是MVCC用到的一致性读视图。它不是真实存在的,而是通过数据更新的不同的trx_id去根据不同版本找到所要的值得。

每个事务都会唯一分配一个自增trx_id,当对数据做更改后,数据会保存当前更改的trx_id。而当前事务开启时,会保存一个trx_id数组,数组内容为当前所有未提交事务trx_id集合和最大trx_id+1的值。其中最小的值叫低水位,最大trx_id+1叫高水位。当前事务能否读到一条数据修改,取决对当前事务trx_id和trx_id数组的比较。

低水位以下

trx_id数组

高水位以上

1、如果查询的数据的更新trx_id在低水位以下,表示是已提交后者当前事务提交的,是可见的

2、如果处在trx_id未提交数组区间中

1)、如果在数组中,表示还未提交,不可见

2)、如果不在数组中,表示已提交,可见

3、如果在高水位以上,则是不可见的

看上面的图,如果当前一条数据分别被事务A,B,C操作,trx_id分别为90,101,100,现在k对应的trx_id=89。

此时A数组对应的trx_id数组为[90,91],B对应的trx_id为[90,100,101,102],C对应的trx_id是[90,100,101]。

由于A读数据,发现此时k=3,trx_id为B的100,100落于A的高水位上,不可见,需要回退,回退到C对应的trx_id=100,也落于高水位上,继续回滚到trx_id=89,落于低水位下,可见。得到K=1的值。

总结:

1、版本未提交,不可见

2、版本已提交,但是在事务开启视图创建之后提交,不可见

3、版本已提交,在事务开启,视图创建之前提交,可见

这就是可重复读隔离级别下的MVCC机制可读性的原理。

但是对于sessionB来说,为什么值是3?

这是因为Mysql在更新时,都需要先读后写,这个读都是读最新的值,就是“当前读”。否则mysql就会丢失C事务的更新操作了。

所以B先读C更新的k=2,再加1,所以再查询得到k=3。

但是如果将C事务提交放在绿色区域(空位C),此时B事务再去修改,由于两阶段锁的作用,C事务还未释放锁,B拿不到锁,只能等待,直到C提交。

到这里,我们就把MVCC一致性读,当前度和两阶段锁联系起来了。

现在,如果我们修改数据库的事务隔离级别为读已提交。

由于with consistent snapshot 是即时创建可重复读视图,所以读已提交下,该语句等同于begin。所以A查到的值为2,B为3。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值