天天看点

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

一、MVCC解决了什么问题?

主要解决的是多个事务并发引起的问题。

原本道理上来说读写和写读是不能并发的。但是如果不能并发的话,数据库的效率就会非常低,所以才会引入MVCC。

本文结合以下链接及自己的验证猜测得出的结论。并没有看过源码。

https://blog.csdn.net/LO_YUN/article/details/111319170

https://www.cnblogs.com/itZhy/p/8831947.html

请先理解readview和undolog版本链。

此外每次生成readview都会携带这几个字段:

  • m_ids:此时有哪些事务在MySQL中执行还没提交
  • min_trx_id:m_ids里最小的值
  • max_trx_id:MySQL下一个要生成的事务id,就是最大事务id
  • creator_trx_id:当前你这个事务的id

每条数据都有两条重要的隐藏字段:一个是trx_id,代表最近最近一次更新这条数据的事务id,另一个字段是roll_pointer,这个字段指向了这个实际undo log的回滚日志。

我认为m_ids,min_trx_id,max_trx_id应该是指针类型的,指向同一条trx_id的这三个字段指向同一个地址(个人猜想,觉得这样才解释得通,如有时间,会好好找下相关文档求证,现在假设是这样的)

readview的生成时机

事务的隔离级别有四个:

  • read uncommitted(读未提交) :解决脏写
  • read committed(读已提交) :解决脏读
  • repeatable read(可重复读):解决不可重复读
  • serializable(串行化):解决幻读

读未提交和串行化使用很少。所以不做讨论(主要是它们也不需要readview)

在开启事务的时候第一条sql语句就会生成readview。

在读已提交的情况下,readivew生成的时机是,其它未提交的事务提交了。就会重新生成readview。

在可重复读的情况下,readivew生成的时机是,自己需要写行锁。就会重新生成readview。

场景

下面只讨论可重复读的情况:

我们假设以下场景:

假设有张表:字段只有id,sum。id是主键。有条记录是(1,0)

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

 此时我们开启三个事务,操作如下。

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

 我们假设当前的txid是100,事务A的txid是101,事务B的txid是102.事务C的txid是103

初始状态:

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

 执行①后:select * from test where id=1,找到的tx_id=101,sum=0

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

执行②后:update test set sum=sum + 10 where id = 1

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

 执行③后:select * from test where id=1,找到的tx_id=101,sum=0

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

  执行④后:select * from test where id=1,找到的tx_id=102,sum=10

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

执行⑤后: commit。

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

 执行⑥后:select * from test where id=1,找到txid=101,sum=0

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

 执行⑦后:update test set sum=sum + 10 where id = 1。会重新生成readview。

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

执行⑧后:select * from test where id=1 ,找到的txid=103.sum=10

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

 执行⑨后:update test set sum=sum + 10 where id = 1,会一直阻塞获取行锁。

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

执行⑩后:commit。事务C的update就会更新readview。

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

执行⑪后:select * from test where id=1 ,找到txid=103,sum=30

MVCC概念一、MVCC解决了什么问题?readview的生成时机场景

这就是就是我理解的MVCC。其实就感觉像是每个事务存了一份快照,只是触发更新的快照的时间不一样。

如有错误望指正!!!

感谢