数据库
首页 > 数据库> > mysql行锁+可重复读+读提交

mysql行锁+可重复读+读提交

作者:互联网

行锁

 

事物隔离      

  

进行以下流程操作:

 

  

 

 

 

 

 对于B来说,遵循更新规则:更新数据都是先读后写的,而这个读,只能读当前的值,称 为“当前读”(current read)。除了update语句外,如果select语句加锁,也是当前读。所以,如果把事务A的查询语句select * from t where id=1修改一下,加上lock in share mode或 for update,也都可以读到版本号是101的数据,返回的k的值是3。

 

 

事务C’的不同是,更新后并没有马上提交,在它提交前,事务B的更新语句先发起了。前面说过了,虽然事务C’还没提交,但是(1,2)这个版本也已经生成了,并且是当前的最新版本。那么,事务B的更新语句会怎么处理呢? 这时候,我们在上一篇文章中提到的“两阶段锁协议”就要上场了。事务C’没提交,也就是说(1,2)这个版本上的写锁还没释放。而事务B是当前读,必须要读最新版本,而且必须加锁,因此就被锁住了,必须等到事务C’释放这个锁,才能继续它的当前读。

 

 可重复读的核心就是一致性读(consistent read);而事务更新数据的时候,只能用当前读。如果当前的记录的行锁被其他事务占用的话,就需要进入锁等待。

而读提交的逻辑和可重复读的逻辑类似,它们最主要的区别是:在可重复读隔离级别下,只需要在事务开始的时候创建一致性视图,之后事务里的其他查询都共用这个一致性视图;在读提交隔离级别下,每一个语句执行前都会重新算出一个新的视图。

 

那么,我们再看一下,在读提交隔离级别下,事务A和事务B的查询语句查到的k,分别应该是多少呢? 这里需要说明一下,“start transaction with consistent snapshot; ”的意思是从这个语句开始,创建一个持续整个事务的一致性快照。所以,在读提交隔离级别下,这个用法就没意义了,等效于普通的start transaction。下面是读提交时的状态图,可以看到这两个查询语句的创建视图数组的时机发生了变化,就是图中的read view框。(注意:这里,我们用的还是事务C的逻辑直接提交,而不是事务C’)

 

 

这时,事务A的查询语句的视图数组是在执行这个语句的时候创建的,时序上(1,2)、(1,3)的生成时间都在创建这个视图数组的时刻之前。但是,在这个时刻: (1,3)还没提交,属于情况1,不可见; (1,2)提交了,属于情况3,可见。 所以,这时候事务A查询语句返回的是k=2。 显然地,事务B查询结果k=3。

 

小结

innoDB的行数据有多个版本,每个数据版本有自己的row trx_id,每个事务或者语句有自己的一致性视图。普通查询语句是一致性读,一致性读会根据row trx_id和一致性视图确定数据版本的可见性。

 

标签:事务,提交,行锁,事物,视图,版本,mysql,id
来源: https://www.cnblogs.com/xiaoxi-jinchen/p/16066017.html