开源openGauss数据库中事务管理源码解析

开源 OpenGauss 数据库中事务管理源码解析

一、 事务状态机

openGauss 将事务系统分为上层(事务块 TBlockState)以及底层(TransState)两个层次。(代码位于 src/gausskernel/storage/access/transam/xact.cpp)

  1. 上层事务块:客户端 query 的状态,用于提高用户操作数据的灵活性,用事务块的形式支持在一个事务中执行多条 query 语句。事务块状态机: 每个事务状态都对应一个事务状态机结构体。

    在无异常情形下,一个事务块的状态机如上图所示按照默认(TBLOCK_DEFAULT)->已开始(TBLOCK_STARTED)->事务块开启(TBLOCK_BEGIN)->事务块运行中(TBLOCK_INPROGRESS)->事务块结束(TBLOCK_END)->默认(TBLOCK_DEFAULT)循环。剩余的状态机是在上述正常场景下的各个状态点的异常处理分支。

    在事务块运行中(TBLOCK_INPROGRESS)出错分为 2 种情形。事务执行失败:事务块运行中(TBLOCK_INPROGRESS)->回滚(TBLOCK_ABORT)->回滚结束(TBLOCK_ABORT_END)->默认(TBLOCK_DEFAULT);用户手动回滚执行成功的事务:事务块运行中(TBLOCK_INPROGRESS)->回滚等待(TBLOCK_ABORT_PENDING)->默认(TBLOCK_DEFAULT)。

  2. 底层(TransState):从内核视角的事务状态,真正意义上的事务状态。事务底层状态:

    内核内部底层状态如上图所示,底层状态机的描述见结构体 TransState。在事务开启前事务状态为 TRANS_DEFAULT。

    事务开启过程中事务状态为 TRANS_START。

    事务成功开启后一直处于 TRANS_INPROGRESS。

    事务结束/回滚的过程中为 TARNS_COMMIT/ TRANS_ABORT。

    事务结束后事务状态回到 TRANS_DEFAULT。

二、 事务状态机系统实例

复制代码
 BEGIN;

    SELECT * FROM TABLE1;

 END;
  1. 整体流程

    任何语句的执行总是先进入事务处理接口事务块中,然后调用事务底层函数处理具体命令,最后返回到事务块中。

  2. BEGIN 执行流程

    (1) 通过入口函数 exec_simple_query 处理 begin 命令。(函数位于\openGauss-server-master\src\gausskernel\process\tcop\postgres.cpp)

    复制代码
    static void exec_simple_query(const char* query_string, MessageType messageType, StringInfo msg = NULL)

    该函数添加默认参数 unint16 messageType。其默认值为 0。如果我们收到混合消息,该参数将设置为 1,以告诉我们正常查询字符串后跟信息字符串。query_string = normal querystring + message

    begin 的 query_string=0x1002cd0"begin;"

    然后我们将 meesageType 与 1 进行比较。当 messageType 为 1 时,表示此消息是混合消息。查询字符串后面是一些我们必须处理的信息。我们将查询字符串分为两部分,普通查询字符串和信息字符串。然后主要调用start_xact_command();

    (void)PortalRun(portal, FETCH_ALL, isTopLevel, receiver, receiver, completionTag);

    finish_xact_command();

    (2) start_xact_command 函数开始一个 query 命令,调用 StartTransactionCommand 函数,此时事务块上层状态未 TBLOCK_DEFAULT,继续调用 StartTransaction 函数,设置事务底层状态 TRANS_START,完成内存、缓存区、锁资源的初始化后将事务底层状态设为 TRANS_INPROGRESS,最后在 StartTransactionCommand 函数中设置事务块上层状态为 TBLOCK_STARTED。<img src='./images/wps6.jpg'><img src='./images/wps7.jpg'> TBLOCK_DEFAULT->TBLOCK_STARTED

    TRANS_DEFAULT->TRANS_START->TRANS_INPROGRESS

    TBLOCK_DEFAULT->TBLOCK_STARTED

    TRANS_DEFAULT->TRANS_START->TRANS_INPROGRESS

    TBLOCK_DEFAULT->TBLOCK_STARTED

    TRANS_DEFAULT->TRANS_START->TRANS_INPROGRESS

    TBLOCK_DEFAULT->TBLOCK_STARTED

(3) PortalRun 处理 begin 语句(4) finish_xact_command finish_xact_command 函数结束一个 query 命令,调用 CommitTransactionCommand 函数设置事务块上层状态从 TBLOCK_BEGIN 变为 TBLOCK_INPROGRESS,并等待读取下一条命令。
  1. Select 语句流程

    (1) exec_simple_query select 的 query_string=0x1002cd0"SELECT * FROM table1;"

    (2) start_xact_command 调用 StartTransactionCommand 函数,由于当前上层事务块状态为 TBLOCK_INPROGRESS,说明已经在事务块内部,则直接返回,不改变事务上层以及底层的状态。

    (3) PortalRun:依次向下调用函数 ExecutorRun 根据执行计划执行最优路径查询。<img src='./images/wps14.jpg'> (4) finish_xact_command 调用 CommitTransactionCommand 函数,当前事务块上层状态仍为 TBLOCK_INPROGESS,不改变当前事务上层以及底层的状态。

  2. Begin 语句流程

    (1) exec_simple_query end 的 query_string=0x1002cd0"end;"

    (2) start_xact_command 调用 StartTransactionCommand 函数,由于当前上层事务块状态为 TBLOCK_INPROGRESS,说明已经在事务块内部,则直接返回,不改变事务上层以及底层的状态。

    (3) PortalRun 设置事务块上层状态为 TBLOCK_END。 (4) finish_xact_command 设置事务底层状态为 TRANS_COMMIT,进行事务提交流程并且清理事务资源;清理后设置底层事务状态为 TRANS_DEFAULT继续调用 CommitTransaction 函数提交事务,设置事务底层状态为 TRANS_COMMIT,进行事务提交流程并且清理事务资源;本地持久化 CLOG 及 XLOG 日志,并清空相应的事务槽位信息。清理后设置底层事务状态为 TRANS_DEFAULT,返回 CommitTansactionCommand 函数;设置事务块上层状态为 TBLOCK_DEFAULT,整个事务块结束。

相关推荐
秋千码途1 小时前
一道同分排名的SQL题
数据库·sql
秋难降3 小时前
零基础学SQL(八)——事务
数据库·sql·mysql
Starry_hello world3 小时前
MySql 表的约束
数据库·笔记·mysql·有问必答
RestCloud4 小时前
ETLCloud中的数据转化规则是什么意思?怎么执行
数据库·数据仓库·etl
一个天蝎座 白勺 程序猿4 小时前
Apache IoTDB(4):深度解析时序数据库 IoTDB 在Kubernetes 集群中的部署与实践指南
数据库·深度学习·kubernetes·apache·时序数据库·iotdb
.Shu.5 小时前
Redis zset 渐进式rehash 实现原理、触发条件、执行流程以及数据一致性保障机制【分步源码解析】
数据库·redis·缓存
君不见,青丝成雪5 小时前
大数据技术栈 —— Redis与Kafka
数据库·redis·kafka
悟能不能悟5 小时前
排查Redis数据倾斜引发的性能瓶颈
java·数据库·redis
DemonAvenger5 小时前
事务管理:ACID特性与隔离级别详解
数据库·mysql·性能优化
xiao-xiang6 小时前
redis-集成prometheus监控(k8s)
数据库·redis·kubernetes·k8s·grafana·prometheus