• Mysql系列三:Innodb MVCC版本控制



    一、Innodb MVCC版本控制

    1、什么是MVCC版本控制?

    MVCC是在并发访问那数据库时,通过对数据版本的控制,避免使用加锁从而造成读取阻塞的情况,比如某个事物进行写操作之后,依然可以读取旧版本的数据,这就是MVCC。

    2、Innodb MVCC 核心

    • 事务版本号 :

    每次开启事务都会有一个唯一id,该id是递增的,可以从id的大小来观察事物开启的顺序。

    • 表的隐藏列:
    DB_TRX_ID记录操作该数据事务的事务ID;
    DB_ROLL_PTR指向上一个版本数据在undo log 里的位置指针;
    DB_ROW_ID隐藏ID ,当创建表没有合适的索引作为聚集索引时,会用该隐藏ID创建聚集索引;
    • undo log :

    回滚日志,记录了事物修改之前的数据信息,当事物回滚时候,通过undo log日志回滚数据。

    用途:

    ​ 1、保证事物rollback时的原子性和一致性,当事物回滚时候,从undo log日志进行恢复。

    ​ 2、在MVCC快照读取时,通过读取undo log日志读取历史数据,以此避免了使用锁从而造成阻塞的问题。

    • read view :
    trx_ids: 当前系统活跃(未提交)事务版本号集合。
    low_limit_id: 创建当前read view 时“当前系统最大事务版本号+1”所以若数据的事物id大于该值,一定在当前事物开启之后提交的。
    up_limit_id: 创建当前read view 时“系统正处于活跃事务最小版本号”,所以若数据的事物id小于该值,一定在当前事物开启之前就已经提交了。
    creator_trx_id: 创建当前read view的事务版本号;

    3、事物版本号、隐藏列、undo log日志的协调工作机制

    假设 user表数据如下所示:

    user表

    开启事物,修改数据

    update user set name = '哈哈哈' where id = 1;
    
    • 1
    • 首先获得一个事物id编号DB_TRX_ID为100
    • 修改user表之前的数据复制到undo log日志中。
    • 修改user表的数据name为哈哈哈
    • 将此时数据的版本号改成当前事务版本号100,把DB_ROLL_PTR作为指向undo log日志的指针,以此找到修改前的数据。

    最后大致如下所示会形成一个版本链:

    undo log

    4、Read view

    在innodb引擎中,每次开启事物都会获得一个read view,内部主要包含了此时活跃事物的信息,以及活跃与非活跃临界值的事物ID,如下所示:

    • trx_ids: 系统中活跃事物版本号的集合。
    • low_limit_id : 创建当前的read view时 当前事物版本号的最大值+1。
    • up_limit_id: 创建当前的read view时,活跃事物版本号的最小值。
    • creator_trx_id: 创建当前read view的事务版本号。

    在读取时,有一下几种情况:

    数据的事物id 简称 dataId

    1、dataId > low_limit_id,则无法显示

    如果事物id比创建read view内的最大事物版本号+1还要大,说明该数据在当前事物开启之后修改的,则无法访问,需要去undo log日志中寻找符合的数据。

    2、dataId < up_limit_id,则显示

    如果事物id比创建read view内的最小活跃事物还要小,说明该数据在开启当前事物之前就已经提交了,可以直接读取。

    3、up_limit_id <= dataId <= low_limit_id,则观察 trx_ids 集合。

    • 查看是否存在该数据的事物版本号,若存在说明操作该条数据的事物还未提交,则无法显示。
    • 若不存在,说明操作该数据的事物已经提交了或就是当前事物操作的,则可以显示。

    以上所有无法显示的情况,都会通过指针去undo log日志中找到前一次的数据,再次通过上述判断是否可以显示,以此递归直到返回数据或返回空。

    5、举例讲解MVCC流程

    MVCC执行流程

    如上所示:

    开启事务A:执行SQL,获得事物id为100

    update user set name ='张三' where id = 3;
    
    • 1

    开启事务B:执行SQL,获得事物id为101

    select * from user where id = 3;
    
    • 1

    事物B会生成read view。

    • trx_ids: [100]
    • low_limit_id : 102
    • up_limit_id: 100
    • creator_trx_id: 101

    然后拿着id为3的数据去与read view进行条件判断:

    1、首先判断100是否比low_limit_id大,若成立不显示,反之继续判断。
    2、判断100是否比up_limit_id小,若小可以显示,反之继续判断。
    3、判断100是否在trx_ids集合内,若在集合内,不显示;反之说明事物已经提交,则显示

    判断之后发现,结果为不显示,则去undo log里面获取修改前的数据,再次判断,若满足显示则返回,若不满足则继续找寻前一条数据,继续判断。

    这儿最终返回的是事物id为99的数据。

    6、InnoDB 引擎不同隔离级别MVCC的区别

    RR级别: 在事物开启后, 只会在事务开启的一瞬间生成一个read view ,所以解决了RC级别不可重复读的问题。

    RC级别: 在事物开启后,每一次查询数据都会生成一个read view,所以有可能出现读取数据不一致的情况。

    7、MVCC是否解决了幻读的问题

    首先严格意义上来说没有, MVCC利用版本链,undo log,Read View可以在快照读模式下解决幻读问题,并且不用加锁解决读写冲突问题,极大的增加了数据库的并发量。 但在当前读模式下仅仅依靠MVCC不能解决幻读问题,必须依赖next-key锁(行锁+gap锁)来解决,这是因为当前读必须获取最新数据。

  • 相关阅读:
    强化学习之REINFORECE策略梯度算法——已CartPole环境为例
    学会iframe并用其解决跨域问题
    基于Java的智能仓库(进销存)管理系统设计与实现(源码+lw+部署文档+讲解等)
    vue CSS 实现上下小三角组件(类似表格排序)
    【信号处理】基于优化算法的 SAR 信号处理(Matlab代码实现)
    线上linux,服务突然不可用(引出Docker文件查找与删除)
    PostgreSQL 空闲空间映射表(FSM)
    植物大战僵尸杂交版全新版v2.1解决全屏问题
    18. 深度学习 - 从零理解神经网络
    2023年MBA/MPA/MEM联考笔试答题抓分点
  • 原文地址:https://blog.csdn.net/zhengguofeng0328/article/details/127883775