Mysql事务MVCC原理

1,156 阅读3分钟

下面探讨一下在Mysql RR和RC隔离级别下 MVCC多版本并发控制,在Mysql中MVCC机制是使用undo log版本链机制实现ReadView机制。

ReadView

ReadView是什么呢,简单来说,ReadView就是在开启一个事务的时候,会给你生成一个ReadView用于实现MVCC机制。下面是ReadView中包含的一些关键的东西

  • m_ids: 这个表示此时mysql事务中有哪些事务还没有提交
  • min_trx_id: 最小事务Id,就是m_ids中最小的一个事务Id
  • max_trx_id: 最大事务Id,就是Mysql下一个要生成的事务Id,就是最大的事务Id
  • creator_trx_id: 当前事务Id

在Mysql中每一个数据行后面都有两个隐藏字段,trx_id和roll_pointer

  • trx_id:当前数据更新的事务Id
  • roll_pointer: 指向下一个undo log版本链,用于查找undo log版本链中数据

image.png

RC ISOLATION实现原理

读已提交:事务只可以读取到已经提交的数据;在Mysql中,通过每一次事务查询都生成一个新的ReadView来实现RC。

MVCC实现RC隔离级别:每一次查询都会新生成一个Readview,可以看下面的例子

1、下面是数据库中的一条数据: image.png

2、如果A事务查询已经提交了的数据,trx_id = 1,这个时候会走一个判断,就是判断一下trx_id小于min_trx_id,那么证明这个数据早在A事务开启之前就已经提交了,所以可以查询到这一条数据。 image.png

3、如果事务B(id = 25) 修改了这一行数据,并且提交了,那么这条数据的trx_id会被更改成trx_id = 25,同时roll_pointer将会指向trx_id = 10的那一条数据,如下undo log版本链。此时事务A再次发起查询,将会生成一个新的ReadView,所以此时trx_id在min_trx_id和ma_trx_id范围之内,同时不在m_ids列表中,所以证明这个事务更改已经提交,在RC隔离级别下是可以读取到的。 image.png

4、当事务A修改了这条数据后,该行数据的trx_id被更改成20,此时trx_id虽然在m_ids列表中,同时当前数据的trx_id的值和ReadView中creator_id的值是一样的,这样说明了这一条数据就是事务A更改的,所以此时A事务来查询是可以查询到的。 image.png

RR ISOLATION实现原理

可重复读:事务A多次查询,结果是一样的;Mysql通过生成一个固定的ReadView实现RR隔离级别的。

MVCC实现RR隔离级别:每一次查询都会用开启事务的时候使用的ReadView,可以看下面的例子

1、下面是数据库中的一条数据: image.png

2、如果事务A(id = 20)和是事务B(id = 25)同时开启事务,那么这个时候的ReadView是: image.png

3、如果此时事务A(id = 20)开启查询,发现当前数据trx_id = 10,小于min_trx_id,那么说明这条数据是在事务A开启之前就已经提交了的,所以这条数据是可以查询到的。 image.png

4、如果此时事务B(id = 25)更改了数据,那么这个时候trx_id = 25, 通过查看A的ReadView可以看到,trx_id = 25在m_ids列表中,所以说明了事务B与事务A是同一时刻启动的事务,所以在RR隔离级别下是不能查询到的。 image.png

5、如果此时事务A(id = 20)再次更改了这条数据,那么此时trx_id = 20, 通过查看A的ReadView可以看到,trx_id = 20在m_ids列表中,但是trx_id = 20与A的ReadView中creator_trx_id的值是一样的,那么说明这个数据是A事务自己更改的,所以是可以查询到的。 image.png

6、如果此时有新的事务C(id = 30)更改了这条数据,那么此时trx_id = 30, 通过查询ReadView可以看到,trx_id = 30不再m_ids列表中,但是trx_id大于max_trx_id, 那么说明这条数据是在A事务开启之后启动的,所以也是不能够查询到的。 image.png

总结

上面主要介绍了MVCC实现RR和RC隔离级别的实现,菜鸟学习总结,大佬勿喷。