侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

MySQL中大对象的多版本并发控制详解

数据库  /  管理员 发布于 6年前   173

MySQL 8.0:InnoDB中大对象的MVCC

在本文中,我将解释MySQL InnoDB存储引擎中大对象(LOB)设计的多版本并发控制(MVCC) 。 MySQL 8.0有一个新功能,允许用户部分更新大型对象,包括JSON文档 。 使用此部分更新功能,当LOB部分更新时,MVCC对LOB的工作方式已发生变化。 对于正常更新(完整更新),MVCC将像以前的版本一样工作。 让我们看一下MVCC在不涉及部分更新时的工作原理,然后考虑对LOB进行部分更新的用例。

MVCC 常规更新

我使用术语常规更新来指代不是部分更新的更新。 我将通过一个例子解释MVCC如何用于常规更新大对象。 我将为此目的使用以下mtr(1)测试用例:

 create table t1 ( f1 int primary key , f2 longblob ) engine = innodb ;  insert into t1 values ( 1 , repeat ( 'a' , 65536 ) ) ;   start transaction ;  update t1 set f2 = repeat ( 'b' , 65536 ) where f1 = 1 ;   -- echo # Connection con1:  -- 对于使用MySQL客户端的用户,可能需要通过另开一个终端窗口建立新链接, 下同。 connect ( con1 , localhost , root , , ) ;  -- echo # Must see the old value 'aaaaaaaaaa'  select f1 , right ( f2 , 10 ) from t1 order by f1 ;   -- echo # Connection default:  connection default ;  disconnect con1 ;  commit ;   drop table t1 ; 

为了理解下面的解释,仔细理解上述测试用例非常重要。

测试场景如下:

最初,表t1包含单个记录(R1)。
事务trx1将记录更新为新值。
当trx1仍处于活动状态时,另一个事务trx2正在读取记录。 它将读取旧值。

表t1仅包含一个记录(R1)。 但是trx1和trx2会看到两个不同的值。 该表实际上只包含最新值(trx1所见的值),而trx2看到的值或记录是从撤消日志记录中获得的。 让我们看下面的图片来更好地理解它。

初始状态:更新操作之前

下图显示了更新操作之前的情况。 撤消日志为空。 表的聚簇索引包含一行。 表中有一个LOB。 聚簇索引记录包含对LOB的引用。

最终状态:更新操作后

现在让我们看一下更新操作后的情况。

以下是一些重要的观察:

用户表空间中有两个LOB - 旧的LOB和新的LOB。 旧的LOB只能通过撤消日志访问。 聚集索引记录指向新LOB。
更新操作已创建包含更新向量的撤消日志记录。 此撤消日志记录指向旧LOB。
聚簇索引记录通过DB_ROLL_PTR系统列指向撤消日志记录。 此滚动指针指向撤消日志记录,该记录可用于构建聚簇索引记录的先前版本。
撤消记录不包含LOB本身。 而是它只包含对存储在用户表空间中的LOB的引用。
存储在撤消日志记录中的LOB引用与存储在聚簇索引记录中的LOB引用不同。

事务在连接1中采取的步骤如下:

事务查看R1并确定尚未提交修改聚簇索引记录的事务。 这意味着它无法读取该记录(因为默认隔离级别是REPEATABLE READ)。
它查看R1中的DB_ROLL_PTR并找到撤消日志记录。 使用撤消日志记录构建R1的先前版本。
它读取了这个构建的旧版R1。 请注意,此版本在聚簇索引记录中不可用。 但它使用撤消记录即时构建。
当R1指向新的LOB时,这个构造的旧版本的R1指向旧的LOB。 所以结果包含旧的LOB。

这是LOB的MVCC在不涉及部分更新时的工作方式。

MVCC部分更新

让我们看另一个例子,了解MVCC在部分更新的情况下是如何工作的。 我们需要另一个例子,因为目前仅通过函数json_set()和json_replace()支持JSON文档的部分更新。

 create table t2 ( f1 int primary key , j json ) engine = InnoDB ;  set @ elem_a = concat ( '"' , repeat ( 'a' , 200 ) , '"' ) ;  set @ elem_a_with_coma = concat ( @ elem_a , ',' ) ;  set @ json_doc = concat ( "[" , repeat ( @ elem_a_with_coma , 300 ) , @ elem_a , "]" ) ;   insert into t2 ( f1 , j ) values ( 1 , @ json_doc ) ;   start transaction ;  update t2 set j = json_set ( j , '$[200]' , repeat ( 'b' , 200 ) ) where f1 = 1 ;   -- echo # Connection con1:  connect ( con1 , localhost , root , , ) ;  -- echo # Must see the old value 'aaaaaaaaaa...'  select json_extract ( j , '$[200]' ) from t2 ;   -- echo # Connection default:  connection default ;  disconnect con1 ;  commit ; 

该场景与前面的示例相同。 只是longblob字段已更改为JSON文档。 加载的数据也略有不同,以符合JSON格式。

提示 :您可以在上述mtr测试用例(两者中)中添加语句set debug ='+ d,innodb_lob_print' ,以在服务器日志文件中打印LOB索引。 LOB索引将在插入后立即打印。 LOB索引将为您提供存储的LOB对象的结构。
在部分更新操作之前

完全或部分更新操作之前的初始条件是相同的,并且已经在上面给出。 但是在下图中,提供了一些附加信息。

让我们看看图中显示的其他信息:

存储在聚簇索引记录中的LOB引用现在包含LOB版本号v1。 在初始插入操作期间,将其设置为1,并在每次部分更新时递增。
每个LOB数据页面在LOB索引中都有一个条目。 每个条目都包含LOB版本信息。 每当修改一个LOB数据页时,它将被复制到具有新数据的新LOB数据页中,并且将创建具有递增的LOB版本号的新LOB索引条目。

附加信息是LOB版本号。 这在聚集索引记录中的LOB引用中以及LOB索引的每个条目中都可用。

部分更新操作后

下图说明了部分更新操作后的情况。

这里最重要的优化是用户表空间中仍然只有一个LOB。 仅更新需要修改的那些LOB数据页。 部分更新操作后的这个单个LOB包含旧版本和新版本的LOB。 图中LOB数据页面上的v1和v2标签说明了这一点。

另一个重要的观察是撤消日志和聚簇索引记录中的LOB引用指向同一个LOB。 但LOB引用包含不同的版本号。 撤消日志记录中的LOB引用包含v1(旧版本号),聚簇索引记录中的LOB引用包含新版本号v2。

LOB版本号的目的

如上所示,具有不同版本号的不同LOB引用指向相同的LOB。 单个LOB包含来自不同版本的部分。 LOB版本号用于获取各种LOB引用指向的正确版本。 在本节中,我们将了解如何完成此操作。

LOB索引包含组成LOB的LOB页面列表。 它包含LOB数据页的页码,每个LOB数据页包含的数据量以及版本号。 此列表的每个节点称为LOB索引条目。 每个LOB索引条目都包含旧版本的列表。 让我们看一个说明上述部分更新测试用例的结构的图。

最初,在完成部分更新之前,LOB索引总共包含4个条目。 四个条目的页码是5,6,7和8.没有LOB索引条目具有旧版本。 所有四个条目的版本号均为1。

部分更新完成后,我们注意到页码9已替换页码7,页码7现在被视为页码9的旧版本。页码9的版本号为2,并且页码7的版本号为1。

部分更新完成后,当通过版本号为1的LOB引用访问LOB时,将查看第5页的第一个索引条目。 它的版本号为1.如果索引条目中的版本号小于或等于 LOB引用中的版本号,则将读取该条目。 因此,将读取第5页。 然后将查看页码为6的索引条目。 它的版本号为1,因此将被读取。 然后将查看页码为9的索引条目。 它的版本号为2.但是lob引用的版本号为1.如果索引条目中的版本号大于LOB引用中的版本号,则不会读取该条目。 由于页码9的条目具有版本2,因此将查看其旧版本。 将检查页码为7的索引条目。 它的版本号为1,因此将被读取。 在此之后,将检查页码为8的索引条目。 它的版本号为1,因此也将被读取。 这是访问旧版LOB的方式。

部分更新完成后,当通过版本号为2的LOB引用访问LOB时,将查看第5页的第一个索引条目。 它的版本号为1.如果索引条目中的版本号小于或等于LOB引用中的版本号,则将读取该条目。 因此它将按顺序读取页码5,6,9,8。 由于版本号始终<= 2,因此无需使用旧版本访问页码7。

需要记住的一点是LOB在InnoDB中不是独立存在的。 它被视为聚簇索引记录的扩展。LOB对事务是否可见并不由LOB模块处理。 LOB模块只是处理聚簇索引记录。 如果事务访问LOB,则意味着它已经在聚簇索引记录中的DB_TRX_ID的帮助下确定它可以查看LOB(而不是LOB的特定版本)。 所以我们不担心LOB模块中的那个方面。 我们只专注于为给定的LOB版本号提供正确的内容。

结论

在本文中,我们了解了如何在InnoDB中为大对象完成MVCC。 当对LOB进行部分更新时,多个LOB引用可以指向同一个LOB。 但他们将拥有不同的版本号。 使用这些LOB版本号,可以访问正确的LOB内容。

希望您发现此信息有用。

谢谢你使用MySQL!

注释:

(1) Mtr即Mini-transaction的缩写,字面意思小事物,相对逻辑事物而言,我们把它称作物理事物。属于Innodb存储引擎的底层模块。主要用于锁和日志信息。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。


  • 上一条:
    mysql中的一些稍微复杂用法实例代码
    下一条:
    深入浅析MySQL从删库到跑路_高级(一)――数据完整性
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 分库分表的目的、优缺点及具体实现方式介绍(0个评论)
    • DevDB - 在 VS 代码中直接访问数据库(0个评论)
    • 在ubuntu系统中实现mysql数据存储目录迁移流程步骤(0个评论)
    • 在mysql中使用存储过程批量新增测试数据流程步骤(0个评论)
    • php+mysql数据库批量根据条件快速更新、连表更新sql实现(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2017-06
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-01
    • 2018-05
    • 2018-10
    • 2018-11
    • 2020-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2021-02
    • 2021-04
    • 2021-07
    • 2021-08
    • 2021-11
    • 2021-12
    • 2022-02
    • 2022-03
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客