开源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,整个事务块结束。

相关推荐
Elastic 中国社区官方博客1 小时前
在 Elasticsearch 中使用 Mistral Chat completions 进行上下文工程
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
编程爱好者熊浪3 小时前
两次连接池泄露的BUG
java·数据库
TDengine (老段)5 小时前
TDengine 字符串函数 CHAR 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
qq7422349845 小时前
Python操作数据库之pyodbc
开发语言·数据库·python
姚远Oracle ACE5 小时前
Oracle 如何计算 AWR 报告中的 Sessions 数量
数据库·oracle
Dxy12393102166 小时前
MySQL的SUBSTRING函数详解与应用
数据库·mysql
码力引擎6 小时前
【零基础学MySQL】第十二章:DCL详解
数据库·mysql·1024程序员节
杨云龙UP6 小时前
【MySQL迁移】MySQL数据库迁移实战(利用mysqldump从Windows 5.7迁至Linux 8.0)
linux·运维·数据库·mysql·mssql
l1t6 小时前
利用DeepSeek辅助修改luadbi-duckdb读取DuckDB decimal数据类型
c语言·数据库·单元测试·lua·duckdb
安当加密6 小时前
Nacos配置安全治理:把数据库密码从YAML里请出去
数据库·安全