暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

openGauss 行存储的多版本管理以及 DML操作

suger 2022-12-14
417

行存储的多版本管理以及 DML操作
openGauss行存储的多版本机制与业界比较常见的关系数据库有较大的不同,核心区别为行存储的多版本在更新的时候并不是就地更新,而是在原有页面中保留上一个版本,转而在这个页面(如果空间不够会在新页面中)中创建一个新的版本进行历史版本的累积与更新。

相应的页面中会同时存有不同版本的同一行数据,拿到不同快照的事务,在读写这些不同版本时互不冲突,有着很好的并发性能。对历史版本的检索可以在页面本身或邻近页面进行,也不需要额外的CPU开销以及IO 开销,有着非常高的效率。同时,事务管理以及持久化角度也变得非常清晰简洁,省去了类似于就地更新所需要的记录、执行以及持久化的 Undo(回退)等相关操作。

以下就以一个 DML的例子简单介绍行存储结构以及 MVCC的实现。

假设我们在一个xid为10的事务中,在一个只有一列varchar(变长字符串类型) 数据的表中插入一条数据 ‘A’,该行数据存入编号为0的数据页面上,则该行存储结构如图5所示。


可以看到xmax为0,此时该记录为有效记录。

假设在此基础上,在事务xid=20中做了删除此行的操作,则此记录的行存储结构如图6所示。


此时xmax被标记为20,如果此事务提交,那么此行最终会被回收。

如果在之前插入(insert)操作的基础上,在事务 xid=30 中连续对该行做两次更新。

第一次更新的行存储结构如图7所示。


原有行失效,通过t-ctid记录新版本的ctid值,进而指向下一行。

第二次更新的行存储结构如图8所示。


第二个版本也变为历史版本,通过ctid指向最新版本,不过值得注意的是,第二个版本的xmin、xmax都为30,即此版本在同一事务中被删除,而最新版本 xmin仍为30,只是t-cid从0增加为1[假设此事务连续执行了两次更新(update)操作]

更新后的页面如图9所示。


以上几个简单的例子比较直观地展示了行存储的基本存储结构、行存储的 DML以及行存储的 MVCC是如何结合在一起共同作用的。

存储引擎内部,索引也是重要的组成部分,索引本身指向存储的是key(键)到ctid(行号)的映射。上面也提到过了,ctid实际上指向的是line_pointer的检索信息,因此索引的页面上存储的信息及其与数据页面的关系如图10所示。



当然,可能会出现更新操作的新版本无法放入旧版本所在页面的情况,这种情况下页面和索引情况的对比如图11所示。


此种情况下,索引会有两条记录(entry),两条记录代表了 key对应新旧版本的ctid,这样方便从索引直接跨页面进行搜索。




原文链接:https://blog.csdn.net/GaussDB/article/details/116012521

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论