MySQL——MVCC实现原理流程分析

发布于:2025-09-14 ⋅ 阅读:(20) ⋅ 点赞:(0)

目录

ReadView可见性规则

不同隔离级别下ReadView的生成时机

流程示例

读已提交级别

可重复读级别


前置知识:https://yjy66.blog.csdn.net/article/details/151332894?fromshare=blogdetail&sharetype=blogdetail&sharerId=151332894&sharerefer=PC&sharesource=m0_74386799&sharefrom=from_link

补充:

ReadView可见性规则

  • 如果行记录的trx_id小于ReadView中的min_trx_id,则该记录对当前的事务可见
  • 如果行记录的trx_id大于ReadView中的max_trx_id,则对当前事务不可见
  • 如果行记录的trx_id在min_trx_id和max_trx_id之间,则检查trx_id是否在ReadView的trx_ids列表中。有两种情况:

          1、如果m_ids包含trx_id,表示ReadView生成时该事务未提交当trx_id等于creator_trx_id,表示数据是自己生成的,可见。否则不可见。

          2、如过m_ids不包含trx_id,说明这个事务在ReadView生成之前就已经提交,可见。

不同隔离级别下ReadView的生成时机

  • READ UNCOMMITTED(读未提交):不生成ReadView。
  • READ COMMITTED(读已提交):每次执行SELECT时生成新的ReadView。
  • REPEATABLE READ(可重复读,MySQL默认):事务第一次执行SELECT生成ReadView。
  • SERIALIZABLE(串行化):不适应ReadView机制。

流程示例

  1. 获取事务自己事务id;
  2. 获取Read View
  3. 查询得到的数据,然后Read View中的事务版本号进行比较。
  4. 如果不符合可见性规则,需要Undo log历史快照。
  5. 最后返回符合规则的数据

读已提交级别

    MySQL的默认隔离级别是可重复读,因此需要修改隔离级别,查询当前事务隔离级别的语句是(MySQL 8.0即以上版本):

SELECT @@transaction_isolation;

    如果是低版本的命令为:

SELECT @@tx_isolation;

可以看到当前的级别都是RR,因此需要修改隔离级别:

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

可以看到成功改为读已提交。


当前初始数据:接下来开启两个事务。

经过一番操作后可以看到,事务A连续查询两次的结果不一样,接下来分析一下流程。

  1. 事务A开启,假设得到的事务id为10.
  2. B开启,得到的事务id为11.
  3. 事务A执行select,生成一个ReadView:
    变量
    m_ids(当前活跃事务id的集合) 10,11                                        
    min_trx_id(最小活跃事务id) 10
    max_trx_id(预分配的事务id) 12
    creator_trx_id(当前事务的id) 10
  4. 接下来根据可见性规则进行判断:在第一次select,行记录的trx_id为10,trx_id=creator_trx_id,所以可见,接下来事务B修改之后并提交,事务A再次查询,由于RC级别每次查询都会生成一个ReadView。
  5. 新的ReadView如下:
    变量
    m_ids(当前活跃事务id的集合) 10                                           
    min_trx_id(最小活跃事务id) 10
    max_trx_id(预分配的事务id) 12
    creator_trx_id(当前事务的id) 10
    此时行记录的trx_id为11,接下来进行可见性判断:trx_id大于min_trx_id,小于max_trx_id,并且m_ids不包含11,所以可见。

可重复读级别

先把事务隔离级别改回RR:

  1. 事务A开启,假设得到的事务id为10.
  2. B开启,得到的事务id为11.
  3. 事务A执行select,生成一个ReadView:
    变量
    m_ids(当前活跃事务id的集合) 10,11                                        
    min_trx_id(最小活跃事务id) 10
    max_trx_id(预分配的事务id) 12
    creator_trx_id(当前事务的id) 10
  4. 接下来根据可见性规则进行判断:在第一次select,行记录的trx_id为10,trx_id=creator_trx_id,所以可见,接下来事务B修改之后并提交,事务A再次查询,RR级别不会再生成新的ReadView
  5. 此时trx_id大于min_trx_id,小于max_trx_id,并且包含在m_ids中,根据可见性规则不可见!

网站公告

今日签到

点亮在社区的每一天
去签到