海山数据库(He3DB)源码详解:CommitTransaction函数源码详解

文章目录

  • 海山数据库(He3DB)源码详解:CommitTransaction函数
    • 1. 执行条件
    • 2. 执行过程
      • 2.1 获取当前节点状态:
      • 2.2 检查当前状态:
      • 2.3 预提交处理:
      • 2.4 提交处理:
      • 2.5 释放资源:
      • 2.6 提交事务:
    • 作者介绍
    • 作者介绍

海山数据库(He3DB)源码详解:CommitTransaction函数

本文介绍了事务提交过程中,具体执行提交任务的CommitTransaction函数详细执行流程。

1. 执行条件

  1. 当事务处于TRANS_INPROGRESS状态且事务块处于TBLOCK_STRATED或者TBLOCK_END状态下,由CommitTransactionCommand函数调用CommitTransaction函数完成提交事务。
  2. 在ParallelWorkerMain函数中由EndParallelWorkerTransaction调用。

2. 执行过程

2.1 获取当前节点状态:

获得当前节点变量值CurrentTransactionState,

并创建两个临时变量latestXid和is_parallel_worker。

    TransactionState s = CurrentTransactionState;TransactionId latestXid;bool		is_parallel_worker;
  1. CurrentTransactionState主要保存了当前事务状态相关的参数,主要是事务状态、事务块状态、XID、保存点、父节点等级等一系列参数。
  2. latestXid用来传递保存XID值。
  3. is_parallel_worker主要用于判断当前事务是否使用并行执行(并行执行指的是数据库将某些查询操作分布到多个工作进程中执行,以提高性能)。

2.2 检查当前状态:

检查并行执行模式,检查当前事务状态并判断父节点状态。

    /* Enforce parallel mode restrictions during parallel worker commit. */if (is_parallel_worker)EnterParallelMode();ShowTransactionState("CommitTransaction");/** check the current transaction state*/if (s->state != TRANS_INPROGRESS)elog(WARNING, "CommitTransaction while in %s state",TransStateAsString(s->state));Assert(s->parent == NULL);
  1. 如果执行并行执行模式,调用EnterParallelMode函数执行++s->parallelModeLevel。
  2. 检查当前事务状态,如果不是TRANS_INPROGRESS,则执行elog函数保存并返回主线程PostgreMain,执行Abort过程。
  3. 断言检查当前父节点状态,出错直接退出(调试用的)。

2.3 预提交处理:

第一、通过死循环处理用户定义的一些延迟触发器和一些portal操作。

    for (;;){/** Fire all currently pending deferred triggers.*/AfterTriggerFireDeferred();/** Close open portals (converting holdable ones into static portals)* If there weren't any, we are done. otherwise loop back to check* if they queued deferred triggers.  Lather, rinse, repeat.*/if (!PreCommit_Portals(false))break;}

这里的死循环行为是:因为,事务(增删改)操作完成之后会触发定义的延迟触发器,进行一些其他的行为,而这些其他行为中可能会包括游标的增删改查,导致了一个套娃操作。所以,这里的AfterTriggerFireDeferred函数处理延迟触发器,PreCommit_Portals处理游标,直到触发器处理完且没有游标需要处理,跳出函数。

  1. 不断调用AfterTriggerFireDeferred函数,在当前事务提交之前调用,执行并处理掉所有待处理的延迟触发器。
  2. 通过判断PreCommit_Portals函数的执行结果,来选择是否跳出死循环。PreCommit_Portals函数的作用,首先是将本次事务过程中的持久化游标物质化,并关闭游标对应需要的执行器,释放持有的锁;然后关闭本次事务过程中的一些非持久门户(Non-holdable portals),其他事务留存下来的持久性门户(Portals)不做改变。如果游标没有做任何操作,即该事务没有其他游标操作,返回false,否则返回true。

持久化游标物质化是指将持久化游标的结果集存储到磁盘或内存中,确保之后的游标查询结果不受后续事务操作对数据的影响。

第二、通过回调函数关闭参数对应的事务内部服务。

    CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_PRE_COMMIT: XACT_EVENT_PRE_COMMIT);

第三、清理并行执行的资源,清理所有的触发器。

    /* If we might have parallel workers, clean them up now. */if (IsInParallelMode())AtEOXact_Parallel(true);/* Shut down the deferred-trigger manager */AfterTriggerEndXact(true);

第四、在关闭游标后调用PreCommit_on_commit_actions函数。

执行ON COMMIT子句定义的行为,包括对临时表的处理和游标的处理等,确保之前的游标都被正确的关闭,不会造成悬空引用(类似于悬空指针)。

    /** Let ON COMMIT management do its thing (must happen after closing* cursors, to avoid dangling-reference problems)*/PreCommit_on_commit_actions();

第五、调用smgrDoPendingSyncs函数和AtEOXact_LargeObject函数。

    /** Synchronize files that are created and not WAL-logged during this* transaction. This must happen before AtEOXact_RelationMap(), * so that we don't see committed-but-broken files after a crash.*/smgrDoPendingSyncs(true, is_parallel_worker);/* close large objects before lower-level cleanup */AtEOXact_LargeObject(true);
  1. smgrDoPendingSyncs函数会在当前事务期间,对那些被创建且其更改没有记录在 WAL(Write-Ahead Logging)日志中的文件进行同步。这是为了确保如果发生崩溃,这些文件的状态是一致的,并且不会留下已提交但损坏的文件。

  2. AtEOXact_LargeObject函数主要是清理一些超出常规字段所能存储限制的“大对象”,关闭与大型对象关联的文件描述符(LO fds),并清空 cookie 数组。

    这样做的结果是,这些文件描述符将不再有效,无法再被用来访问或操作大型对象。无论事务是提交还是中止,持有这些 LO fds 的内存上下文和资源所有者在事务结束时都将被销毁。这意味着这些资源在事务结束时无论如何都会被清理。

    在事务提交的情况下,需要关闭这些 LO fds,以避免在提交时出现关于资源泄露的警告。这是因为在提交时,系统会检查所有资源是否已经被正确管理,包括打开的文件描述符。

    在事务中止的情况下,可以跳过关闭 LO fds 的步骤。这是因为在中止事务时,系统会回滚所有更改,并且通常不需要执行与提交相同的清理操作。

第六、调用PreCommit_Notify函数处理事务提交前与NOTIFY命令相关的操作。

它确保了NOTIFY命令能够在事务提交时正确地通知其他会话或应用程序。

    /** Insert notifications sent by NOTIFY commands into the queue.This* should be late in the pre-commit sequence to minimize time spent* holding the notify-insertion lock.However, this could result in* creating a snapshot,so we must do it before serializable cleanup.*/PreCommit_Notify();

第七、判断当前是否为并行执行模式。

False,执行PreCommit_CheckForSerializationFailure 函数,在事务准备提交时,检查当前事务是否可能与其他事务发生了冲突。如果检测到冲突,函数会抛出一个错误,导致当前事务回滚。(这里主要发生在并发执行情况下或者多个表的复杂查询事务)
通过这种方式,PostgreSQL 确保事务的串行化执行,避免数据不一致的问题。

    /** Mark serializable transaction as complete for predicate locking* purposes.This should be done as late as we can put it and still allow* errors to be raised for failure patterns found at commit.This is not* appropriate in a parallel worker however,because we aren't committing* the leader's transaction and its serializable state will live on.*/if (!is_parallel_worker)PreCommit_CheckForSerializationFailure();
  1. 串行化是事务隔离级别中最高的级别,它确保事务的执行就像它们是串行执行的一样,避免了所有并发问题。
  2. 可序列化事务(Serializable Transaction):可序列化事务是数据库事务的最高隔离级别,它通过完全串行化事务的执行来避免所有类型的并发问题,如脏读、不可重复读和幻读。
  3. 谓词锁定(Predicate Locking):谓词锁定是一种数据库锁定技术,用于锁定满足特定条件的数据行,而不是锁定整个表或数据页。这允许更细粒度的并发控制。

第八、关闭中断机制,清理重置映射,正式开始提交事务清理资源。

    /* Prevent cancel/die interrupt while cleaning up */HOLD_INTERRUPTS();/* Commit updates to the relation map --- do this as late as possible */AtEOXact_RelationMap(true, is_parallel_worker);

2.4 提交处理:

第一、修改事务状态,开始事务提交

    /** set the current transaction state information appropriately during* commit processing*/s->state = TRANS_COMMIT;s->parallelModeLevel = 0;

第二、根据并行事务状态,处理日志。

检查并行执行状态。不是并行事务,调用RecordTransactionCommit函数记录当前XID的日志。是并行事务,则调用ParallelWorkerReportLastRecEnd函数处理WAL日志,将当前XID置为InvalidTransactionId。

    if (!is_parallel_worker){/** We need to mark our XIDs as committed in pg_xact.This is where we* durably commit.*/latestXid = RecordTransactionCommit();}else{/** We must not mark our XID committed; the parallel leader is* responsible for that. */latestXid = InvalidTransactionId;/** Make sure the leader will know about any WAL we wrote before it* commits. */ParallelWorkerReportLastRecEnd(XactLastRecEnd);}

ParallelWorkerReportLastRecEnd函数的目的是确保领导者进程在我们提交事务之前知道工作者进程已经写入的所有 WAL 日志。这是必要的,因为在并行事务处理中,领导者进程需要等待所有工作者进程完成它们的任务,并且记录了它们所有的更改,然后才能安全地提交整个事务。

第三、通知系统当前进程(MyProc)已经结束了一个事务。

ProcArrayEndTransaction 函数用于通知系统当前进程(MyProc)已经结束了一个事务,并且提供了要结束的事务 XID(latestXid)。ProcArrayEndTransaction 调用的顺序要求:

  1. 必须在释放当前进程持有的锁之前执行。这是因为在锁释放之前,其他进程需要知道当前进程已经结束了事务,以避免潜在的死锁或资源争用问题。
  2. 同时,它也必须在 RecordTransactionCommit 调用之后执行。RecordTransactionCommit 函数用于记录事务提交到 WAL(Write-Ahead Logging)日志,确保事务的持久性。
    ProcArrayEndTransaction(MyProc, latestXid);

ProcArrayEndTransaction函数标记了一个事务不在运行。从这一步以后,即便出错也来不及阻止事务提交了,后续都是资源的释放和参数重置过程。

2.5 释放资源:

第一、释放TopTransactionResourceOwner所拥有的资源。

  1. AtEOXact_Buffers函数清理缓冲区。
  2. AtEOXact_RelationCache函数清理关系缓存。
  3. AtEOXact_Inval函数在主事务结束时处理排队中的无效信息。
  4. AtEOXact_MultiXact函数结束多事务。
    ResourceOwnerRelease(TopTransactionResourceOwner,RESOURCE_RELEASE_BEFORE_LOCKS,true, true);/* Check we've released all buffer pins */AtEOXact_Buffers(true);/* Clean up the relation cache */AtEOXact_RelationCache(true);/** Make catalog changes visible to all backends.This has to happen after* relcache references are dropped (see comments for* AtEOXact_RelationCache), but before locks are released (if anyone is* waiting for lock on a relation we've modified, we want them to know* about the catalog change before they start using the relation). */AtEOXact_Inval(true);AtEOXact_MultiXact();ResourceOwnerRelease(TopTransactionResourceOwner,RESOURCE_RELEASE_LOCKS,true, true);ResourceOwnerRelease(TopTransactionResourceOwner,RESOURCE_RELEASE_AFTER_LOCKS,true, true);

ResourceOwnerRelease函数释放参数TopTransactionResourceOwner及其后代拥有的所有资源,但不删除“资源Owner”对象本身。

第二、处理删除操作并通知事务成功完成。

    smgrDoPendingDeletes(true);/** Send out notification signals to other backends (and do other* post-commit NOTIFY cleanup).  This must not happen until after our* transaction is fully done from the viewpoint of other backends.*/AtCommit_Notify();

第三、依次清理资源。

  1. AtEOXact_GUC(true, 1);
    处理:运行时配置参数(GUC)。
    作用:在事务结束时应用或撤销事务期间设置的配置更改。
  2. AtEOXact_SPI(true);
    处理:服务器过程接口(SPI)。
    作用:清理 SPI 在事务中使用的资源和状态。
  3. AtEOXact_Enum();
    处理:枚举类型。
    作用:管理枚举类型的元数据,确保事务结束后枚举状态是一致的。
  4. AtEOXact_on_commit_actions(true);
    处理:提交时执行的动作。
    作用:执行在事务提交时需要进行的特定动作或回调。
  5. AtEOXact_Namespace(true, is_parallel_worker);
    处理:命名空间。
    作用:清理命名空间相关的资源,可能与并行工作有关。
  6. AtEOXact_SMgr();
    处理:存储管理器。
    作用:管理文件和存储相关的资源,如释放锁或处理文件删除。
  7. AtEOXact_Files(true);
    处理:文件资源。
    作用:清理事务中使用的文件,如临时文件。
  8. AtEOXact_ComboCid();
    处理:组合命令 ID。
    作用:管理与组合命令 ID 相关的事务状态。
  9. AtEOXact_HashTables(true);
    处理:哈希表。
    作用:清理或刷新哈希表,确保数据结构的一致性。
  10. AtEOXact_PgStat(true, is_parallel_worker);
    处理:pg_stat 统计信息。
    作用:更新统计收集模块的状态,可能与并行工作有关。
  11. AtEOXact_Snapshot(true, false);
    处理:事务快照。
    作用:清理事务快照,确保 MVCC 状态下的数据可见性正确。
  12. AtEOXact_ApplyLauncher(true);
    处理:逻辑复制应用启动器。
    作用:管理逻辑复制相关的事务结束时的资源和状态。
  13. pgstat_report_xact_timestamp(0);
    处理:事务时间戳统计。
    作用:报告事务的时间戳信息给 pg_stat 模块,0 可能表示当前时间或其他特定值。
    /** Everything after this should be purely internal-to-this-backend* cleanup.*/AtEOXact_GUC(true, 1);AtEOXact_SPI(true);AtEOXact_Enum();AtEOXact_on_commit_actions(true);AtEOXact_Namespace(true, is_parallel_worker);AtEOXact_SMgr();AtEOXact_Files(true);AtEOXact_ComboCid();AtEOXact_HashTables(true);AtEOXact_PgStat(true, is_parallel_worker);AtEOXact_Snapshot(true, false);AtEOXact_ApplyLauncher(true);pgstat_report_xact_timestamp(0);

第四、重置全局变量和状态变量。

重置CurrentResourceOwner、XactTopFullTransactionId、CurTransactionResourceOwner、TopTransactionResourceOwner、nParallelCurrentXids和事务状态变量TransactionState s。ResourceOwnerDelete函数会删除TopTransactionResourceOwner参数的对象及其后代。

    CurrentResourceOwner = NULL;ResourceOwnerDelete(TopTransactionResourceOwner);s->curTransactionOwner = NULL;CurTransactionResourceOwner = NULL;TopTransactionResourceOwner = NULL;AtCommit_Memory();s->fullTransactionId = InvalidFullTransactionId;s->subTransactionId = InvalidSubTransactionId;s->nestingLevel = 0;s->gucNestLevel = 0;s->childXids = NULL;s->nChildXids = 0;s->maxChildXids = 0;XactTopFullTransactionId = InvalidFullTransactionId;nParallelCurrentXids = 0;

2.6 提交事务:

修改事务状态为TRANS_DEFAULT,放开中断机制,完成事务提交。

    s->state = TRANS_DEFAULT;RESUME_INTERRUPTS();

作者介绍

李超,移动云数据库工程师,负责云原生数据库He3DB的研发。
0;
s->childXids = NULL;
s->nChildXids = 0;
s->maxChildXids = 0;
XactTopFullTransactionId = InvalidFullTransactionId;
nParallelCurrentXids = 0;


### 2.6 提交事务:
> 修改事务状态为TRANS_DEFAULT,放开中断机制,完成事务提交。```c++s->state = TRANS_DEFAULT;RESUME_INTERRUPTS();

作者介绍

李超,移动云数据库工程师,负责云原生数据库He3DB的研发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/52322.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构-线性表-了解循环链表

了解循环链表 循环链表是一种特殊的链表结构,其中最后一个节点的指针指向头节点,从而形成一个闭环。循环链表可以分为两种类型:单循环链表和双循环链表。 1. 单循环链表(Singly Circular Linked List) 定义&#xf…

Qt第十八章 XML和Json格式解析

文章目录 JSON格式解析Json生成案例 XML简介与HTML的区别格式XML解析流的方式DOM XML生成 JSON与XML的区别比较 JSON 格式 JSON是一个标记符的序列。这套标记符包含六个构造字符、字符串、数字和三个字面名 六个构造字符 开始和结束数组:[ ]开始和结束对象&#x…

基于HarmonyOS的宠物收养系统的设计与实现(一)

基于HarmonyOS的宠物收养系统的设计与实现(一) 本系统是简易的宠物收养系统,为了更加熟练地掌握HarmonyOS相关技术的使用。 项目创建 创建一个空项目取名为PetApp 首页实现(组件导航使用) 官方文档:组…

安卓中设置渐变字体和描边字体

1.CommonFontSpan abstract class CommonFontSpan : ReplacementSpan() {/** 测量的文本宽度 */private var mMeasureTextWidth 0foverride fun getSize(paint: Paint,text: CharSequence?,start: Int,end: Int,fontMetricsInt: FontMetricsInt?): Int {mMeasureTextWidth…

机器学习辅助复合材料预测,性能管理优化创新材料,这种王炸般的组合,还真是大开眼界!

在人工智能与复合材料技术融合的背景下,复合材料的研究和应用正迅速发展,创新解决方案层出不穷。从复合材料性能的精确预测到复杂材料结构的智能设计,从数据驱动的材料结构优化到多尺度分析,人工智能技术正以其强大的数据处理能力…

Eureka 原理与实践全攻略

一、Eureka 概述 Eureka 在微服务架构中具有举足轻重的地位。它作为服务注册与发现的核心组件,为分布式系统中的服务管理提供了关键支持。 Eureka 的主要功能包括服务注册、服务发现、服务健康监测和自我保护机制。服务注册功能使得服务提供者能够在启动时将自身的…

git-版本管理工具基本操作-创建仓库-拉取-推送-暂存库-版本库

1、创建仓库和版本说明 2、克隆仓库到本地(首次拉取需要输入用户名和密码,用户名用邮箱,密码用登录gitee的密码,后面配置密钥后可以直接clone) 在命令行输出两行指令配置git才能克隆: username&#xff1…

JUnit 断言验证

assertEquals(expected, actual): 检查 actual 是否等于 expected。示例: assertEquals(5, myMethod(2, 3)); // 检查 2 3 是否等于 5 assertTrue(condition): 检查 condition 是否为 true。示例: assertTrue(myMethod(1) > …

求数组中出现次数超过一半的数字

一、题目 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 假设数组非空,并且一定存在满足条件的数字。 思考题: 假设要求只能使用 O(n)的时间和额外 O(1)的空间,该怎么做呢? 数据范围 数组长度…

《Web项目跨域请求后端Api设置Cookie失败问题?》

问题描述: 在web项目中跨域请求api时,api登录成功后需要向域名中设置cookie实现在两个域名下共享,但是登录接口返回成功,响应头中也有set-cookie,实际却无法设置到cookie中… web项目访问时的域名https://b.com/ api所…

解锁Spring Boot、Prometheus与Grafana三合一:打造你的专属自定义指标炫酷大屏!

1. 集成Prometheus到Spring Boot 需要在Spring Boot应用中集成Prometheus。可以通过micrometer库来实现。micrometer是一个应用程序监控库,它支持多种监控系统,包括Prometheus。 一招制胜!Spring Boot、Prometheus和Grafana三剑合璧&#x…

一、react-hooks(useState、useRef、forwardRef)

一、useState 注意事项: 1.setState的方法并不像函数式组件会自动合并,所以需要我们通过展开运算符手动合并。 // 更新方式1:展开运算符// const info{...userInfo,...data}// setUserInfo(info)// 方式2:setUserInfo(Object.as…

roscpp 实现深度图像与RGB图像的对齐

目录 通用内容通用可视化函数topic订阅版可视化深度图像的callback直接读取rosbag版通用内容 放到代码最上面 #include <ros/ros.h> #include <sensor_msgs/Image.h> #include <cv_bridge/cv_bridge.h> #include <opencv2/opencv.hpp> //#include &l…

银河麒麟服务器操作系统Kylin-Server-V10-SP3-2403-Release-20240426-x86_64安装步骤

银河麒麟服务器操作系统 Kylin-Server-V10-SP3-2403-Release-20240426-x86_64安装步骤 一、准备工作1. 下载ISO镜像2. 制作安装介质3. 设置BIOS 二、安装过程1. 启动系统2. 选择安装语言3. 选择安装配置4. 配置root密码与创建用户5. 开始安装6. 重启系统7. 同意许可协议 三、系…

【sql】加密所有的存储程式

因项目管理规定&#xff0c;所有的存储程式&#xff08;SP&#xff09;都需要加密。 如何批量加密所有的SP呢&#xff1f; 在网上找到了参考的代码&#xff0c;然后发现除SP外连同View,Trigger,Function等也可以一并处理&#xff01; 参考资料&#xff1a; https://download.…

【Redis】基本全局命令

Redis的基本全局命令 keysexistsdelexpirettltype Redis 有 5 种数据结构&#xff0c;但它们都是键值对种的值&#xff0c;对于键来说有⼀些通⽤的命令。 keys 返回所有满足样式 &#xff08;pattern&#xff09;的key。支持如下统配样式。 h?llo 匹配 hello , hallo 和 hxl…

七、SPA单页面实现SEO优化之SSR服务器渲染

文章目录 一、前言&#xff1a;二、SSR基本操作步骤 一、前言&#xff1a; 关于SPA和SEO优化、SSR服务器渲染的介绍可以参考这里&#xff1a; 六、什么是SEO优化&#xff08;搜索引擎优化&#xff09;&#xff1f;SPA单页面应用如何实现SEO优化&#xff1f; 通过上一篇文章可…

2024 实训室建设:1+X 老年生活照护实训室

摘要&#xff1a;本文探讨了 2024 年 1X 老年生活照护实训室的建设意义、设计理念、功能布局以及对老年照护人才培养的积极作用&#xff0c;旨在为提升老年生活照护水平提供有力的实践教学支持。 随着我国老龄化进程的加速&#xff0c;对高质量老年生活照护的需求日益增长。202…

JAVA红黑树TreeMap/TreeSet详解

Java中的红黑树是一种自平衡的二叉查找树&#xff0c;它通过特定的旋转和重新着色操作来确保树的高度大致保持在对数级别&#xff0c;从而在平均和最坏情况下都能保证查找、插入、删除等操作的时间复杂度为O(log n)。红黑树通过遵循一系列的性质来维持其平衡&#xff1a; 红黑…

培训班和科班出生有什么区别

IT业的萌新来啦 每到毕业季 总有大量萌新走进职场 IT圈子的程序员 有的是科班出生 比如 计算机科学与技术、软件工程、大数据技术 有的是相关专业出生的 比如 信息安全、网络工程、物联网工程等等 除此之外 还有各种其他专业转行过来的 文理不限、专业不限 科班出生…