写点什么

PostgreSQL 和 InnoDB 的多版本实现原理和比较

  • 2009-11-12
  • 本文字数:2343 字

    阅读完需:约 8 分钟

在风清扬的博客多版本并发控制:PostgreSQL vs InnoDB 中很好的阐述了 PostgreSQL 和 InnoDB 的多版本并发控制原理,并根据自己的丰富经验进行了深入的对比。

多版本并发控制技术被很多数据库或存储引擎采用,如 Oracle,MS SQL Server 2005+, PostgreSQL, Firebird, InnoDB, Falcon, PBXT, Maria 等等。新的数据库存储引擎,几乎毫无例外的使用多版本而不是单版本加锁的方法实现并发控制,可以说多版本已经成为未来的发展趋势。

PostgreSQL 的多版本实现原理 (基于 8.4.1 版本)

PostgreSQL 采用堆 +B+ 树索引(忽视 R 树、哈希、GiST 等不常用的索引)的存储结构,堆与索引的存储模式不同。

PostgreSQL 里记录的新老版本都存在堆里,堆中每条记录 header 里都通过 t_xmin 和 t_xmax 来存储创建事务 ID(creation transaction id)和销毁事务 ID(destruction transaction id)。在他的另一篇博客从对数据访问扭曲的适应性评价 PostgreSQL 与 InnoDB 里很简洁地介绍了这个实现策略:

PostgreSQL 处理多版本的简单逻辑是这样的:一个事务更新一个记录时产生一个新版本,并设置新版本的产生事务 ID 和和原版本的消亡事务 ID 为该事务 ID。新旧版本除被组织成一个链表外,其物理存储没有任何其它联系,就好像是两个记录一般。事务在读取到一个版本时,通过这两个事务 ID 与当前事务 ID 之间的关系来判断它是否应该看到这个版本。这一实现策略相当简洁(对索引的多版本存储尤其是如此),通过索引访问时更不会有对回滚段的额外访问,可以消除事务回滚的代价。

更详细的数据结构和函数可以参考 Inside PostgreSQL Shared Memory 等文章。除此之外,事务提交日志和事务快照也被用来进一步保存版本的信息,包括事务的状态和当时活跃事务的列表等。而对于 PostgreSQL,其索引是没有版本信息的。 通常更新每一条记录都会在该记录所在表的所有索引中插入相应的索引项。他在文中说这样会导致进行索引扫描时,即使查询所需所有属性在索引中都存在,也需要从堆中取出对应的记录判断是否可见除了:

在 PostgreSQL 8.3 中引入了 HOT(Heap-Only-Tuple)技术,如果新老版本在同一页面,并且 UPDATE 没有更新任何索引属性,则不插入新版本对应的索引项。

对于事务的提交和回滚操作,风清扬认为:

事务提交或回滚时操作简单,除事务提交时要写出事务外,只需要更新事务提交日志中对应的事务状态。也就是说回滚时并不需要将事务所作的操作从物理上清理掉,只要将事务状态设为已经回滚,则该事务产生的版本对其它事务自然就不可见了。

他也给出了不需要的老旧版本的不可见处理方式:

老旧的不再需要的版本,即不会被将来的任何事务见到的版本的清理是通过 VACUUM 实现的。由于新老版本混杂在一起,进行 VACUUM 时本质上是需要扫描所有数据。8.4 版中引入了 Visibility Map 技术,用来在 VACUUM 时跳过那些肯定不包含老旧版本的页面,但如果系统更新频繁且离散,这一技术就派不上大用场。在线的 VACUUM 只能清理页面中的老旧版本,但不能缩减表占用的空间,其实是产生碎片。要缩减表空间时的 VACUUM 会锁住表导致期间表不能被更新。

InnoDB 的多版本实现(基于 MySQL 5.1.33 版本带的 InnoDB)

InnoDB 采用索引组织表的存储结构,没有堆,记录存储在主键索引中,其它索引称为二级索引,其中每个索引项都包含所对应记录的主键。主键索引与二级索引的存储格式也不同。

InnoDB 的主键索引拥有版本化信息,除了主键被更新的情况需要存储多个版本,其他情况主键索引中只存储记录的最新版本,把旧版本的信息则集中存储在回滚段中:

主键索引记录的头上包含有 6 字节的事务 ID 与 7 字节指向回滚段中旧版本的指针。DELETE 时只是标记而不真正删除。UPDATE 时进行本地更新,并将前像写到回滚段中。

InnoDB 中读视图(和 PostgreSQL 中事务快照类似),也记录了事务开始时的活跃事务列表:

根据读视图和记录头上的事务 ID,可以判断出一个版本在事务开始时是否已经提交,即是否可见。如果存储在主键索引中的记录不可见,则根据指向回滚段中旧版本的指针找到旧版本信息,构造出旧的记录。回滚段采用的是 append-only 的日志型存储,记录的旧版本信息并不是一条完整的记录,而只是被更新的属性的前像。回滚段中的旧版本信息中也包含更旧的版本的位置,即版本链表是从新到旧的。

对于 InnoDB 的事务处理:

由于没有事务日志表示事务是否回滚,在事务回滚时必须清理该事务所进行的修改,插入的记录要删除,更新的记录要更新回来。事务提交时则无需处理。

如前所说,InnoDB 的二级索引中的每个索引项并没有版本化信息:

但在页面头记录了对该页面操作的事务的 ID 的最大值,通过这一值可以判断页面中是否可能包含不可见的数据,如果是,则需要访问主键索引判断可见性。否则,可以直接从索引中获取查询所需属性。二级索引中可能存储一条记录的多个索引对应的索引项,如果 UPDATE 操作更新了某个索引的属性,则类似于 PostgreSQL,插入新索引项到二级索引中,老索引项并不删除。但没有被 UPDATE 操作更新的索引则不需要插入新索引项。

在文章的最后,作者分享了他个人对这两种实现方式的评价,优势为:

PostgreSQL 与 InnoDB 的多版本实现最大的区别在于最新版本和历史版本是否分离存储,PostgreSQL 不分,InnoDB 分。

相对于 InnoDB,PostgreSQL 的优势似乎主要的只有一条:事务回滚可以立即完成,无论事务进行了多少操作。查询以前的历史数据的功能并不常用,在目前的 PostgreSQL 中也并不实用。

劣势为:

InnoDB 的主要劣势在于事务回滚时需要清理事务所作的所有修改,因此使用 InnoDB 时要避免使用超大型事务,否则回滚可能超慢无比。

而 PostgreSQL 的主要劣势在于清理老版本的扫描代价,索引属性更新时引起的索引项频繁插入,堆空间的回收问题以及判断算法的复杂性和开销等。更深入的介绍请参考风清扬博客。

2009-11-12 23:414091
用户头像

发布了 42 篇内容, 共 19.1 次阅读, 收获喜欢 6 次。

关注

评论

发布
暂无评论
发现更多内容

企业为什么要实施信息化体系建设

优秀

企业信息化 信息化 信息化系统

通义灵码上下文能力解析:自由组合需求描述,生成结果更高效

阿里云云效

阿里云 云原生 通义灵码

【CodeBuddy】三分钟开发一个实用小功能之:动态文字路径动画

jimaks

CSS

NAS远程访问选哪个?内网穿透工具对比:贝锐花生壳完胜节点小宝

科技热闻

蚂蚁集团数字蚂力与珀莱雅战略合作:打造AI智能化应用矩阵 提升消费者体验和企业竞争力

Lily

#放码来战.端云一体化开发#HarmonyOS 5 【农民叔叔】04.创建端云一体化工程项目

与辉鸿蒙

HarmonyOS HarmonyOS NEXT 端云一体化

#放码来战.端云一体化开发#HarmonyOS 5 【农民叔叔】01.人工智能AI诊断分析农作物病虫害APP介绍

与辉鸿蒙

HarmonyOS NEXT 端云一体化 HarmonyOS5.0

全国独家线下面授 | 大规模敏捷LeSS认证上海6月19-21日【报名享多重福利优惠】

ShineScrum

#放码来战.端云一体化开发#HarmonyOS 5 【农民叔叔】02.核心功能操作路径及ModelArts AI图像识别技术

与辉鸿蒙

HarmonyOS HarmonyOS NEXT

"催化型领导力(Catalyst Leadership)" 敏捷领导者CAL 1认证 · 8月9-10日(周末班)

ShineScrum

“从PMO到VMO价值交付管理” — Agile VMO业务敏捷CVP认证 | 7月26-27日 · 上海线下

ShineScrum

MySQL 派生表查询导致 Crash 的根源分析与解决方案

GreatSQL

WebGL与APP之间的通讯方式

北京木奇移动技术有限公司

软件外包公司 webgl开发 webgl外包公司

CST软件TDR时域仿真实例

思茂信息

cst CST软件 CST Studio Suite

鸿蒙 HarmonyOS NEXT 系统 Preference 首选项使用全解析

威哥爱编程

HarmonyOS HarmonyOS NEXT Harmony5

轻帆云ITSM:以AI赋能制造业,构建高效运维新范式

云智慧AIOps社区

ITSM ITSM软件 工单管理系统

从炫技到实用,天工超级智能体(Skywork Super Agents)的破冰之旅

脑极体

AI

#放码来战.端云一体化开发#HarmonyOS 5 【农民叔叔】03.什么是端云一体化开发,有什么优势?

与辉鸿蒙

HarmonyOS HarmonyOS NEXT

极兔快递Java岗,薪资18-35K,看看难度

王中阳Go

Java

#放码来战.端云一体化开发#HarmonyOS 5 【农民叔叔】06.部署模板示例的云测工程到AGC云端

与辉鸿蒙

HarmonyOS HarmonyOS NEXT 端云一体化

四位图灵奖掌舵 2025智源大会揭示AI进化新路径

智源研究院

提升开发运维效率:原力棱镜游戏公司的 Amazon Q Developer CLI 实践

亚马逊云科技 (Amazon Web Services)

HarmonyOS NEXT 使用 relationalStore 实现数据库操作

威哥爱编程

#放码来战.端云一体化开发#HarmonyOS 5 【农民叔叔】05.端云一体化开发工程目录结构

与辉鸿蒙

HarmonyOS HarmonyOS NEXT 端云一体化

从三流作者到虎嗅公众号头条——我的AI写作方法论

田威AI

AI

通义灵码上下文能力解析:自由组合需求描述,生成结果更高效

阿里巴巴云原生

阿里云 云原生 通义灵码

YashanDB:助力企业攻克AI时代数据管理难题,拥抱智能转型

极客天地

【CodeBuddy】三分钟开发一个实用小功能之:3D旋转相册

jimaks

CSS

WebGL与App的集成开发

北京木奇移动技术有限公司

软件外包公司 webgl开发 webgl外包开发

2025北京国际人形机器人展览会

AIOTE智博会

机器人展 智能机器人展 人形机器人展

英特尔至强6家族又添新成员:释放GPU潜能,AI性能更出色

E科讯

PostgreSQL和InnoDB的多版本实现原理和比较_数据库_晁晓娟_InfoQ精选文章