mysql的MVCC机制

一、undo log版本链

  我们在执行update,insert,delete的时候会生成undo log日志,以防止回滚使用。

  一条sql执行,会生成一条undo log日志:

 

 

  其中trx_id就是执行这条sql的事务id,roll_pointer指向对同一个值修改的undo log日志,因为当前没有,就指向一个空对象。

      又有一个sql对这个数据进行修改,事务id为51,值改为B:

 

 

  对同一条数据进行修改,通过roll_pointer连起来,就形成了undo log版本链。

 

二、ReadView机制

  执行一个事务的时候生成一个ReadView,ReadView包括:

  1.m_ids:还未提交的事务id

      2.min_trx_id:m_ids中最小的事务id

      3.max_trx_id:mysql生成的下一个事务id

      4.creator_trx_id:当前事务id,也就是创建这个Read View的事务id

 

  比如现在有事务A,事务B对数据进行修改,事务A生成的Read View:

 

 

 

三、mysql的RR级别实现原理

  那么mysql的MVCC机制如何基于undo log版本链和ReadView来实现呢?

  我们看看mysql默认的RR级别,解决了脏读、不可重复读、幻读等问题:

  脏读:事务B开启,undo log生成一条日志。此时事务A来查询,值为B的这条undo log,trx_id为60,比事务A中ReadView的creator_trx_id:50要大,说明在事务A开启前执行的,查一下m_ids果然在这个集合里面,说明这个事务和事务A同时进行的,继续向下走。下一条日志的trx_id为50,就是自己事务的id可以查询,返回值A。这就解决了脏读的问题。

  不可重复读:在事务B开启前,事务A查询到的值为A。提交后,事务A查询到的值还是A,解决了不可重复读的问题。

  幻读:比如执行一条sql:select count(*) where id>10;

  事务A刚开始查询时,满足条件的只有3条。事务B此时插入一条数据,id为6。事务A来查询,id>10的数据,发现复合查询条件的有2条,一条为原始3条,一条为事务B提交后的4条。事务A比较trx_id比事务B的小,而且在m_ids中,所以返回的是原始数据那条还是3。这就解决了幻读的问题。

  

posted @ 2020-04-20 00:16  东篱闲菊  阅读(407)  评论(0编辑  收藏  举报