服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Mysql - MVCC多版本控制机制:MySQL事务时光机!

MVCC多版本控制机制:MySQL事务时光机!

2023-12-06 14:10码农本农 Mysql

MVCC机制是通过read-view机制与undo log版本链比对机制,使得不同的事务会根据数据版本链对比规则读取同一条数据在版本链上的不同版本数据。

多事务操作同一行数据的时候,就会出现各种并发问题,mysql通过四种隔离级别来解决这些问题,

读未提交隔离级别是最宽松的,基本没有做隔离,所以实现起来很简单;

读提交隔离级别是每次执行语句(包括查询和更新语句)的时候都会生成一个一致性视图,从而保证当前事务可以看到其他事务提交后的数据;

可重复读隔离级别的实现是每个事务在开启的时候都会生成一个一致性视图,当其他事务有提交后也不会影响当前事务中的数据,要保证这一点mysql是通过多版本控制机制MVCC来实现的。

可串行化隔离级别的隔离级别比较高,是通过加锁来实现,所以mysql有一套锁机制。

读提交和可重复读隔离级别都是依赖于MVCC多版本控制机制实现,今天我们就来讨论mysql中的MVCC多版本控制机制

1MVCC多版本控制机制

MVCC机制是通过read-view机制与undo log版本链比对机制,使得不同的事务会根据数据版本链对比规则读取同一条数据在版本链上的不同版本数据。

undo log版本链

事务在开启的时候首先会申请一个事务id:ransaction id

事务对某行数据做修改操作的时候,Mysql会保留修改前的数据undo回滚日志,并且把事务id:ransaction id赋值给版本记录中的字段trx_id。

把这些undo log日志串联起来形成一个历史记录版本链,如图

MVCC多版本控制机制:MySQL事务时光机!图片

注意这里的版本记录不是真实物理存在的,真实物理存在只有最新的一条记录,其他历史记录都是通过回滚日志推导出来的。

read-view机制

可重复读隔离级别和读提交隔离级别是通过生成一个一致性视图来实现,这个一致性视图就是read-view。

一致性视图是什么

MVCC多版本控制机制:MySQL事务时光机!图片

一个事务启动的时候,innodb会为这个事务构造一个数组,用来保存这个事务的启动瞬间正在活跃的所有事务id。“活跃”指的是启动了,但是没提交。

数组里面id最小的值即为低水位,最大的值+1记为高水位,这便是一致性视图。

每个事务在做查询的时候会根据一致性视图的可见性规则去undo log版本链中推导对应的数据。

一致性视图的可见性规则

  1. 如果当前事务id落在绿色部分,表示这个版本是已提交的事务或者是当前事务自己生成的,这个数据是可见的;
  2. 如果当前事务id落在红色部分,表示这个版本是由将来启动的事务生成的,是肯定不可见的;
  3. 如果当前事务id落在黄色部分,那就包括两种情况:

a. 若 row trx_id在数组中,表示这个版本是由还没提交的事务生成的,不可见;

b. 若 row trx_id不在数组中,表示这个版本是已经提交了的事务生成的,可见。

2案例

MVCC多版本控制机制:MySQL事务时光机!图片

图中事务A查询的i是什么?我们先来分析一下。

按照从上到下事务开启的顺序,每个事务对应的一致性视图如下:

事务A的一致性视图数组[11]

事务B的一致性视图数组[11,12]

事务C的一致性视图数组[11,12,13]

事务A在查询的那个时刻,undo log版本链是:

{trx_id=11,id=1,i=10,roll_pointer=0}>>>{trx_id=13,id=1,i=11,roll_pointer=1}>>>{trx_id=12,id=1,i=12,roll_pointer=2}

“{}”  代表的是版本记录

“>>>” 代表的是回滚日志undo log

事务A在查询的时候,事务B和事务C属于未来事务,对事务A是不可见的。因此事务A查询的数据是通过最新的数据记录根据undo log不断向前回滚才得到的数据:i=10。

再看一个案例

MVCC多版本控制机制:MySQL事务时光机!图片

事务A查询1结果是什么?

事务A查询2结果是什么?

由一致性视图可见性规则分析,对事务A来说,事务B是未来事务,对事务A是不可见的,因此查询结果i=10。

查询2的结果i=12,为什么呢?先来看看两个概念

在可重复读隔离级别中这种通过回滚日志找到对应版本记录的读取方式就是一致性读

而不需要回滚,永远只需要读取最新版本记录的方式就是当前读

事务中如果有更新语句的话,更新语句都是以当前读的方式读取到版本记录中最新数据,然后再进行更新操作,因此上图中的查询结果为i=12。

下面两种查询方式也是当前读:

select k from t where id=1 lock in share mode;

select k from t where id=1 for update;

以上便是MVCC机制,按照其规则,这种机制只有在可重复读隔离级别和读提交隔离级别下才会有。

原文地址:https://mp.weixin.qq.com/s/yFaSVFhRsaeXjrkWbKytag

延伸 · 阅读

精彩推荐
  • MysqlMySql 1067错误与编码问题的解决方案

    MySql 1067错误与编码问题的解决方案

    MySql 大部分都是用绿色版(解压版) 然后注册服务简单方便,但是配置文件也很让人纠结,下面小编给大家带来了MySql 1067错误与编码问题的解决方案,感兴趣...

    zhouixi2192020-06-30
  • MysqlMySQL数据库超时设置配置的方法实例

    MySQL数据库超时设置配置的方法实例

    这篇文章主要给大家介绍了关于MySQL数据库超时设置配置的相关资料,通过文中的设置方法可以很好的解决大家遇到的mysql数据库超时问题,需要的朋友可以参...

    张松然9762021-11-23
  • Mysqlwin10下mysql5.7.21解压版安装教程

    win10下mysql5.7.21解压版安装教程

    这篇文章主要为大家详细介绍了win10下mysql5.7.21解压版安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    穿裤衩的文叔2892020-08-25
  • MysqlMySQL使用命令创建、删除、查询索引的介绍

    MySQL使用命令创建、删除、查询索引的介绍

    今天小编就为大家分享一篇关于MySQL使用命令创建、删除、查询索引的介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友...

    CODETC4882020-09-15
  • MysqlMySQL 的自增主键一定是连续的吗?

    MySQL 的自增主键一定是连续的吗?

    众所周知,自增主键可以让聚集索引尽量地保持递增顺序插入,避免了随机查询,从而提高了查询效率但实际上,MySQL 的自增主键并不能保证一定是连续递...

    飞天小牛肉4832022-12-06
  • Mysqlmysql索引失效的几种情况分析

    mysql索引失效的几种情况分析

    这篇文章主要给大家介绍了关于mysql索引失效的情况,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    path哥10172021-04-23
  • Mysqlmysql之delete删除记录后数据库大小不变

    mysql之delete删除记录后数据库大小不变

    这篇文章主要介绍了mysql之delete删除记录后数据库大小不变的相关资料,需要的朋友可以参考下...

    爱上猫的鱼4142020-06-15
  • Mysqlmysql定时删除过期数据记录的简单方法

    mysql定时删除过期数据记录的简单方法

    今天小编就为大家分享一篇mysql定时删除过期数据记录的简单方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    简一_hz4462020-11-30