开源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 分钟前
从0到1:企业级AI项目迭代日记 Vol.90|Agent变快了,Judge定下来了
大数据·数据库·人工智能·ai编程·企业ai
冰之杍4 分钟前
MySQL utf8mb3 → utf8mb4 完整修改方案
数据库·mysql
老纪的技术唠嗑局29 分钟前
端侧智能爆火之后,为何模型反而不是主角了?
数据库·人工智能
这个DBA有点耶43 分钟前
一文讲透数据库分类:关系型、非关系型、OLTP、OLAP、分布式、多模……
数据库·mysql·架构
Macbethad1 小时前
使用Rigol DHO924示波器连接上位机进行24小时波形数据记录的技术报告
数据库
茉莉玫瑰花茶2 小时前
SQL 调优 [ 1 ]
数据库·sql
Databend2 小时前
从传统分区到微分区,Snowflake 与 Databend 如何减少数据扫描
大数据·数据库·sql
ruleslol2 小时前
Redis 雪崩与服务降级
数据库·redis
易番番ERP3 小时前
品牌代理商SKU繁多,ERP如何高效处理新旧规格替换?
数据库·微服务·云原生·sku·易番番erp
leo_yu_yty3 小时前
Mysql 面试准备
数据库·mysql·面试