当前位置: 首页 > news >正文

MYSQL之MVCC多版本并发控制实现原理

InnoDB多版本并发控制

InnoDB 是一个数据多版本的存储引擎。它保留有关已更改行的旧版本的信息,以支持并发性和回滚等事务性特性。此信息存储在系统表空间中,或在undo 表空间中称为回滚段的数据结构中。InnoDB使用回滚段中的信息来执行事务回滚中所需的撤消操作,它还会使用这些信息来构建具有一致性读的行的早期版本(即多版本快照读)。

InnoDB默认会为每行数据添加三个隐式字段

  • 一个6字节的DB_TRX_ID字段表示插入或更新该行的最后一个事务的事务标识符。此外,删除在内部被视为一个更新,其中行中的一个特殊位被设置为将其标记为已删除。
  • 一个7字节的DB_ROLL_PTR字段,称为回滚指针。回滚指针指向undo log中的回滚段记录。如果行被更新,则undo log日志将记录更新行之前重建行内容所需的信息。(实际就是通过此指针,将最新行记录和旧的版本记录链接在一起,成为一个链表,MVCC机制的快照读用到了此链表)
  • 一个6字节的DB_ROW_ID字段包含一个行ID,它随着插入新行而单调地增加。如果InnoDB自动生成一个聚簇索引,则该索引包含行ID值。否则,DB_ROW_ID列将不会出现在任何索引中。

回滚段中的undo log分为insert日志和update日志。Insert undo logs仅在事务回滚时需要,一旦事务提交,可以立刻丢弃。只有在没有事务为InnoDB分配了一个快照,在快照读中可能需要Update undo logs中的信息来构建数据库行的早期版本时,它们才能被丢弃。 (即当前非最新的update undo log没有任何事务用它来构建快照读视图时可以丢弃)。

建议定期提交事务,包括只有快照读的事务,否则,InnoDB不能丢弃update undo log中的旧记录数据, rollback segment可能会越来越大,从而填充增大它所在的表空间。

回滚段的undo log记录的物理大小通常小于相应的插入或更新的行,你可以使用此信息来计算回滚段所需的空间。

在InnoDB多版本控制方案中,当你使用sql语句删除行时,不会立即从数据库中物理删除该行。InnoDB只有在丢弃为删除写入的update undo log记录时,才会物理删除相应的行及其索引记录 。这个删除操作称为清除,它的清除速度非常快,通常与执行删除的sql语句相同。

如果你在表中以几乎相同的速率插入和删除行,清除线程可能会开始滞后,并且因“dead”行表越来越大,使得所有行都被磁盘绑定,速度非常慢。在这种情况下,请限制新的行操作,并通过调整innodb_max_purge_lag系统变量来为清除线程分配更多的资源 。

多版本并发控制和辅助索引

InnoDB多版本并发控制(mvcc)对辅助索引的处理不同于聚簇索引。聚簇索引中的记录将就地更新,它们隐藏的系统列指向undo log日志项,可以从中重建早期版本的记录。 不同于聚簇索引,辅助索引记录不包含隐藏的系统列,也不进行就地更新。

当辅助索引列更新时,将对旧的辅助索引记录进行删除标记,插入新记录,并最终清除有删除标记的记录。 当辅助索引记录被标记删除或辅助索引页被新的事务更新时,innodb将在聚簇索引中查找数据库记录。在聚簇索引中,检查记录的DB_TRX_ID,如果在启动读取事务后修改了记录,则从undo log中检索记录的正确版本。

如果辅助索引记录被标记需要删除或辅助索引页被新的事务更新,InnoDB在聚簇索引结构中查找记录,而不是从索引结构中返回值。

但是,如果启用了索引条件下推(icp)优化,并且其中的where条件只能使用索引中的字段进行评估,mysql服务器仍然将这部分的where条件下推到存储引擎,在那里使用索引对其进行评估。如果没有找到匹配的记录,则会避免进行聚簇索引查找 。如果找到匹配的记录,即使是在有删除标记的记录中,InnoDB也会在聚簇索引中查找该记录。

MVCC实现原理小结

通过上面官方的概述,我们知道,MVCC是为了提高数据库读写并发而采取的一种数据多版本控制机制。数据库并发除了读写并发还有写写并发,写写并发只能通过程序控制,悲观锁或乐观锁

相关文章:

  • TQZC706开发板教程:10G光口arp测试
  • 第四章 Three.js 绘制基本几何体
  • web移动前端网页:深度剖析与未来展望
  • Ubuntu 设置开机启动脚本
  • 【Pytorch】计算机视觉项目——卷积神经网络TinyVGG模型图像分类(如何使用自定义数据集)
  • 【人工智能】第三部分:ChatGPT的应用场景和挑战
  • 【教程】让小爱音箱Play增强版接入Mi-GPT
  • Android Jetpack Compose 实现一个电视剧选集界面
  • C#——方法函数详情
  • DNN模型介绍
  • 国外创意二维码应用:飞利浦旧物翻新活动,传播可持续性消费的重要性!
  • 【C语言】一节课拿捏---动态内存分配
  • SpringBoot:CORS是什么?SpringBoot如何解决跨域问题?
  • 【UML用户指南】-15-对高级结构建模-对象图
  • linux操作系统怎么看设备管理器
  • JavaScript-如何实现克隆(clone)函数
  • $translatePartialLoader加载失败及解决方式
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • bootstrap创建登录注册页面
  • ES6系列(二)变量的解构赋值
  • oldjun 检测网站的经验
  • 服务器从安装到部署全过程(二)
  • 前端面试总结(at, md)
  • # .NET Framework中使用命名管道进行进程间通信
  • ###项目技术发展史
  • (06)金属布线——为半导体注入生命的连接
  • (2024,Vision-LSTM,ViL,xLSTM,ViT,ViM,双向扫描)xLSTM 作为通用视觉骨干
  • (二十六)Java 数据结构
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • .Net Core 微服务之Consul(二)-集群搭建
  • .net 后台导出excel ,word
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded
  • .NET成年了,然后呢?
  • /etc/skel 目录作用
  • @NestedConfigurationProperty 注解用法
  • [ C++ ] STL_list 使用及其模拟实现
  • [.NET]桃源网络硬盘 v7.4
  • [100天算法】-x 的平方根(day 61)
  • [AHK] WinHttpRequest.5.1报错 0x80092004 找不到对象或属性
  • [AI StoryDiffusion] 创造神奇故事,AI漫画大乱斗!
  • [BUG]vscode插件live server无法自动打开浏览器
  • [BZOJ4016][FJOI2014]最短路径树问题
  • [C/C++]关于C++11中的std::move和std::forward
  • [C/C++]数据结构----顺序表的实现(增删查改)
  • [C++]类和对象【上篇】
  • [EULAR文摘] 利用蛋白组学技术开发一项蛋白评分用于预测TNFi疗效
  • [FSCTF 2023]细狗2.0
  • [html] 动态炫彩渐变背景
  • [LaTex]arXiv投稿攻略——jpg/png转pdf
  • [office] excel如何计算毛重和皮重的时间间隔 excel计算毛重和皮重时间间隔方法 #笔记#学习方法
  • [pytorch] 2. tensorboard
  • [Spring Cloud Task]3 框架配置详解
  • [SUCTF 2019]EasySQL1 题目分析与详解