【参天引擎】事务生命周期 / MVCC / Undo / ACID / 分布式事务 功能域整体解析

事务管理架构

阅读时间: 约 55 分钟

难度等级: ⭐⭐⭐⭐⭐(高级)


文章目录

  • 事务管理架构
    • 背景
    • 一、功能域总览
    • 二、事务生命周期管理
      • [2.1 BEGIN / COMMIT / ROLLBACK 流程](#2.1 BEGIN / COMMIT / ROLLBACK 流程)
      • [2.2 事务状态机](#2.2 事务状态机)
      • [2.3 knl_xact_t 结构](#2.3 knl_xact_t 结构)
    • [三、事务 ID 管理](#三、事务 ID 管理)
      • [3.1 Global XID 组成](#3.1 Global XID 组成)
      • [3.2 事务槽(tx slot)分配/回收](#3.2 事务槽(tx slot)分配/回收)
      • [3.3 分布式事务标识](#3.3 分布式事务标识)
    • [四、MVCC 多版本并发控制](#四、MVCC 多版本并发控制)
      • [4.1 SCN 快照读](#4.1 SCN 快照读)
      • [4.2 版本链(Undo)](#4.2 版本链(Undo))
      • [4.3 可见性判断](#4.3 可见性判断)
      • [4.4 读视图(ReadView)](#4.4 读视图(ReadView))
    • [五、ACID 实现机制](#五、ACID 实现机制)
    • [六、Undo 段管理](#六、Undo 段管理)
      • [6.1 Undo 段分配](#6.1 Undo 段分配)
      • [6.2 Undo 记录格式](#6.2 Undo 记录格式)
      • [6.3 Undo 回滚](#6.3 Undo 回滚)
      • [6.4 Undo 空间回收](#6.4 Undo 空间回收)
    • [七、Savepoint 实现](#七、Savepoint 实现)
    • [八、事务持久化(Transaction 层面的 Redo 写入)](#八、事务持久化(Transaction 层面的 Redo 写入))
    • [九、分布式事务协调(DTC 事务)](#九、分布式事务协调(DTC 事务))

背景

事务管理是 Cantian 数据库 ACID 特性的核心实现层,位于 SQL 执行层与内核存储引擎之间。它涵盖完整的事务生命周期(BEGIN/COMMIT/ROLLBACK)、全局 XID 分配与事务槽管理、基于 Undo 版本链的 MVCC 多版本并发控制、Savepoint 回滚点支持、以及集群环境下的分布式事务协调。本章深入解析事务管理的各子模块架构与核心实现机制。

文章亮点:

  • ✅ 完整的事务状态机:从 IDLE → ACTIVE → COMMITTING/ROLLING_BACK → 清理的全链路分析
  • ✅ MVCC 可见性判断四规则与 Undo 版本链回溯机制
  • ✅ 全局 XID 三段式设计与分布式事务标识
  • ✅ ACID 四大特性的底层实现原理对照
  • ✅ XA 两阶段提交在集群环境下的协调流程
  • ✅ 事务 Redo 写入的四个层面与持久化保障

一、功能域总览

事务管理功能域涵盖 Cantian 数据库 ACID 特性的全部核心实现,从事务生命周期管理到 MVCC 多版本并发控制,从 Undo 段管理到分布式事务协调。事务层位于内核存储引擎之上、SQL 执行层之下,是连接会话管理、日志系统、缓冲池、集群通信的枢纽。
#mermaid-svg-U9b34LYFsGQIVLyE{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-U9b34LYFsGQIVLyE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-U9b34LYFsGQIVLyE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-U9b34LYFsGQIVLyE .error-icon{fill:#552222;}#mermaid-svg-U9b34LYFsGQIVLyE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-U9b34LYFsGQIVLyE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-U9b34LYFsGQIVLyE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-U9b34LYFsGQIVLyE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-U9b34LYFsGQIVLyE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-U9b34LYFsGQIVLyE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-U9b34LYFsGQIVLyE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-U9b34LYFsGQIVLyE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-U9b34LYFsGQIVLyE .marker.cross{stroke:#333333;}#mermaid-svg-U9b34LYFsGQIVLyE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-U9b34LYFsGQIVLyE p{margin:0;}#mermaid-svg-U9b34LYFsGQIVLyE .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-U9b34LYFsGQIVLyE .cluster-label text{fill:#333;}#mermaid-svg-U9b34LYFsGQIVLyE .cluster-label span{color:#333;}#mermaid-svg-U9b34LYFsGQIVLyE .cluster-label span p{background-color:transparent;}#mermaid-svg-U9b34LYFsGQIVLyE .label text,#mermaid-svg-U9b34LYFsGQIVLyE span{fill:#333;color:#333;}#mermaid-svg-U9b34LYFsGQIVLyE .node rect,#mermaid-svg-U9b34LYFsGQIVLyE .node circle,#mermaid-svg-U9b34LYFsGQIVLyE .node ellipse,#mermaid-svg-U9b34LYFsGQIVLyE .node polygon,#mermaid-svg-U9b34LYFsGQIVLyE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-U9b34LYFsGQIVLyE .rough-node .label text,#mermaid-svg-U9b34LYFsGQIVLyE .node .label text,#mermaid-svg-U9b34LYFsGQIVLyE .image-shape .label,#mermaid-svg-U9b34LYFsGQIVLyE .icon-shape .label{text-anchor:middle;}#mermaid-svg-U9b34LYFsGQIVLyE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-U9b34LYFsGQIVLyE .rough-node .label,#mermaid-svg-U9b34LYFsGQIVLyE .node .label,#mermaid-svg-U9b34LYFsGQIVLyE .image-shape .label,#mermaid-svg-U9b34LYFsGQIVLyE .icon-shape .label{text-align:center;}#mermaid-svg-U9b34LYFsGQIVLyE .node.clickable{cursor:pointer;}#mermaid-svg-U9b34LYFsGQIVLyE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-U9b34LYFsGQIVLyE .arrowheadPath{fill:#333333;}#mermaid-svg-U9b34LYFsGQIVLyE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-U9b34LYFsGQIVLyE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-U9b34LYFsGQIVLyE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-U9b34LYFsGQIVLyE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-U9b34LYFsGQIVLyE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-U9b34LYFsGQIVLyE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-U9b34LYFsGQIVLyE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-U9b34LYFsGQIVLyE .cluster text{fill:#333;}#mermaid-svg-U9b34LYFsGQIVLyE .cluster span{color:#333;}#mermaid-svg-U9b34LYFsGQIVLyE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-U9b34LYFsGQIVLyE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-U9b34LYFsGQIVLyE rect.text{fill:none;stroke-width:0;}#mermaid-svg-U9b34LYFsGQIVLyE .icon-shape,#mermaid-svg-U9b34LYFsGQIVLyE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-U9b34LYFsGQIVLyE .icon-shape p,#mermaid-svg-U9b34LYFsGQIVLyE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-U9b34LYFsGQIVLyE .icon-shape .label rect,#mermaid-svg-U9b34LYFsGQIVLyE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-U9b34LYFsGQIVLyE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-U9b34LYFsGQIVLyE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-U9b34LYFsGQIVLyE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 数据结构
核心机制
事务生命周期
BEGIN/START TRANSACTION
ACTIVE

活跃状态
COMMITTING

提交中
ROLLING_BACK

回滚中
COMMIT/ROLLBACK
MVCC多版本并发控制

SCN快照读/版本链/可见性判断
Undo段管理

Undo分配/记录/回滚/回收
ACID实现

原子性/一致性/隔离性/持久性
XA分布式事务

两阶段提交/协调
全局XID

SegNode+SegId+SlotId
事务槽tx_slot

状态/SCN/Undo位置
Undo记录

版本链/回滚信息

| 组件 | 核心职责 | 关键源码目录 |

|------|----------|-------------|

| 事务生命周期 | BEGIN / COMMIT / ROLLBACK,事务状态机 | kernel/xact/ |

| 事务 ID 管理 | 全局 XID 分配/回收,事务槽管理 | kernel/include/xact_defs.h |

| MVCC | SCN 快照读,Undo 版本链,可见性判断 | 文档25 |

| Undo 管理 | Undo 段分配,Undo 回滚,空间回收 | 文档20 |

| ACID | 原子性、一致性、隔离性、持久性 | 文档22 |


二、事务生命周期管理

2.1 BEGIN / COMMIT / ROLLBACK 流程

#mermaid-svg-lRy0x7El5ATmy0UI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lRy0x7El5ATmy0UI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lRy0x7El5ATmy0UI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lRy0x7El5ATmy0UI .error-icon{fill:#552222;}#mermaid-svg-lRy0x7El5ATmy0UI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lRy0x7El5ATmy0UI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lRy0x7El5ATmy0UI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lRy0x7El5ATmy0UI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lRy0x7El5ATmy0UI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lRy0x7El5ATmy0UI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lRy0x7El5ATmy0UI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lRy0x7El5ATmy0UI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lRy0x7El5ATmy0UI .marker.cross{stroke:#333333;}#mermaid-svg-lRy0x7El5ATmy0UI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lRy0x7El5ATmy0UI p{margin:0;}#mermaid-svg-lRy0x7El5ATmy0UI defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-lRy0x7El5ATmy0UI g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-lRy0x7El5ATmy0UI g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-lRy0x7El5ATmy0UI g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-lRy0x7El5ATmy0UI g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-lRy0x7El5ATmy0UI g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-lRy0x7El5ATmy0UI .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-lRy0x7El5ATmy0UI .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-lRy0x7El5ATmy0UI .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-lRy0x7El5ATmy0UI .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-lRy0x7El5ATmy0UI .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-lRy0x7El5ATmy0UI .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-lRy0x7El5ATmy0UI .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-lRy0x7El5ATmy0UI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lRy0x7El5ATmy0UI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-lRy0x7El5ATmy0UI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lRy0x7El5ATmy0UI .edgeLabel .label text{fill:#333;}#mermaid-svg-lRy0x7El5ATmy0UI .label div .edgeLabel{color:#333;}#mermaid-svg-lRy0x7El5ATmy0UI .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-lRy0x7El5ATmy0UI .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-lRy0x7El5ATmy0UI .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-lRy0x7El5ATmy0UI .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-lRy0x7El5ATmy0UI .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-lRy0x7El5ATmy0UI .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lRy0x7El5ATmy0UI .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lRy0x7El5ATmy0UI #statediagram-barbEnd{fill:#333333;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lRy0x7El5ATmy0UI .cluster-label,#mermaid-svg-lRy0x7El5ATmy0UI .nodeLabel{color:#131300;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-lRy0x7El5ATmy0UI .note-edge{stroke-dasharray:5;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-note text{fill:black;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram-note .nodeLabel{color:black;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagram .edgeLabel{color:red;}#mermaid-svg-lRy0x7El5ATmy0UI #dependencyStart,#mermaid-svg-lRy0x7El5ATmy0UI #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-lRy0x7El5ATmy0UI .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-lRy0x7El5ATmy0UI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 会话建立
BEGIN / 第一条DML
执行DML语句
COMMIT
ROLLBACK / 异常
Redo落盘
清理事务上下文
Undo回滚完成
清理事务上下文
IDLE
ACTIVE
COMMITTING
ROLLING_BACK
COMMITTED
ROLLED_BACK
修改数据

生成Undo

持有锁
写Commit Redo

释放锁

标记事务槽
遍历Undo链

逐条回滚

释放锁

| 阶段 | 关键操作 | 源文件 |

|------|----------|--------|

| BEGIN | 分配事务 ID(XID),初始化事务上下文 knl_xact_t | knl_tran.c |

| DML 执行 | 分配 Undo 空间,记录 Undo,获取锁 | knl_undo.c |

| COMMIT | 写 Commit Redo,标记事务槽为已提交,释放锁 | knl_xact_log.c |

| ROLLBACK | 遍历 Undo 记录链,逆向执行回滚,释放锁 | knl_undo.c |

2.2 事务状态机

事务状态由 xact_status_t 枚举定义(位于 xact_defs.h):

| 状态 | 值 | 说明 |

|------|-----|------|

| XACT_END | 0 | 事务结束(初始/终结状态) |

| XACT_BEGIN | 1 | 事务活跃 |

| XACT_PHASE1 | 2 | XA 两阶段提交 - 准备阶段 |

| XACT_PHASE2 | 3 | XA 两阶段提交 - 提交/回滚阶段 |

DML 执行期间的更多内部状态通过事务项(txn_t)的标志位和 knl_xact_t 结构维护。

2.3 knl_xact_t 结构

knl_xact_t 是事务管理的核心数据结构,记录一个活跃事务的全部上下文:

  • 事务标识 : 全局 XID(xid_t

  • 时间戳 : 事务开始 SCN(scn_t)、SSN(ssn_t

  • Undo 信息: 当前 Undo 段号、Undo 页面、Undo 槽位

  • 锁信息: 持有的行锁列表、表锁列表

  • 隔离级别: READ_COMMITTED / CURR_COMMITTED / SERIALIZABLE

  • XA 事务信息 : knl_xa_xid_t 格式标识、全局事务 ID

源文件入口:knl_tran.h


三、事务 ID 管理

3.1 Global XID 组成

Cantian 的全局事务 ID(XID)由三部分组成:

| 组成部分 | 位宽 | 说明 |

|----------|------|------|

| SegNode (段节点号) | 实例 ID | 标识事务所属节点,通过 XID_INST_ID(xid) 宏提取 |

| SegId (段号) | 段内编号 | 标识事务使用的 Undo 段,通过 XID_SEG_ID(xid) 宏提取 |

| SlotId(槽号) | 槽内编号 | 标识事务在 Undo 段页面中的槽位 |

XID 结构定义与宏展开见 knl_tran.h

c 复制代码
#define XID_INST_ID(xid)      ((xid).xmap.seg_id / GS_MAX_UNDO_SEGMENT)

#define XID_SEG_ID(xid)       ((xid).xmap.seg_id % GS_MAX_UNDO_SEGMENT)

3.2 事务槽(tx slot)分配/回收

  • 分配 : 在 Undo 段页面中寻找空闲事务槽(txn_t),分配 XID 并初始化

  • 回收: 事务提交或回滚后,将事务槽标记为空闲

  • 页面常量 : 每个页面可容纳的事务数量由 TXN_PER_PAGE(session) 宏决定

  • 并发安全: 通过页面 Latch 保护事务槽的并发分配

3.3 分布式事务标识

在集群环境下,XID 包含实例 ID 信息,确保不同节点的事务 ID 全局唯一:

  • 同一 Undo 表空间中,不同实例分配到不同的 Undo 段区间

  • XA 分布式事务使用额外的 knl_xa_xid_t 结构标识全局事务


四、MVCC 多版本并发控制

MVCC 通过 Undo 版本链实现事务隔离,保证读不阻塞写、写不阻塞读。详见 文档25

4.1 SCN 快照读

  • 每个查询在开始时获取当前全局 SCN 作为快照 SCN

  • 快照 SCN 存储在会话的 query_scn 字段中

  • 查询只能看到提交 SCN ≤ 快照 SCN 的数据版本

4.2 版本链(Undo)

  • 数据页的 ITL(Interested Transaction List)指向最新修改的事务

  • 该事务的 Undo 记录包含修改前的数据(前镜像)

  • Undo 记录可能链接到更早的 Undo 记录,形成版本链

  • 通过遍历版本链可以构造任意历史时间点的数据快照

#mermaid-svg-oLVm5RK4NpDxSz2S{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-oLVm5RK4NpDxSz2S .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-oLVm5RK4NpDxSz2S .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-oLVm5RK4NpDxSz2S .error-icon{fill:#552222;}#mermaid-svg-oLVm5RK4NpDxSz2S .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-oLVm5RK4NpDxSz2S .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-oLVm5RK4NpDxSz2S .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-oLVm5RK4NpDxSz2S .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-oLVm5RK4NpDxSz2S .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-oLVm5RK4NpDxSz2S .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-oLVm5RK4NpDxSz2S .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-oLVm5RK4NpDxSz2S .marker{fill:#333333;stroke:#333333;}#mermaid-svg-oLVm5RK4NpDxSz2S .marker.cross{stroke:#333333;}#mermaid-svg-oLVm5RK4NpDxSz2S svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-oLVm5RK4NpDxSz2S p{margin:0;}#mermaid-svg-oLVm5RK4NpDxSz2S .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-oLVm5RK4NpDxSz2S .cluster-label text{fill:#333;}#mermaid-svg-oLVm5RK4NpDxSz2S .cluster-label span{color:#333;}#mermaid-svg-oLVm5RK4NpDxSz2S .cluster-label span p{background-color:transparent;}#mermaid-svg-oLVm5RK4NpDxSz2S .label text,#mermaid-svg-oLVm5RK4NpDxSz2S span{fill:#333;color:#333;}#mermaid-svg-oLVm5RK4NpDxSz2S .node rect,#mermaid-svg-oLVm5RK4NpDxSz2S .node circle,#mermaid-svg-oLVm5RK4NpDxSz2S .node ellipse,#mermaid-svg-oLVm5RK4NpDxSz2S .node polygon,#mermaid-svg-oLVm5RK4NpDxSz2S .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-oLVm5RK4NpDxSz2S .rough-node .label text,#mermaid-svg-oLVm5RK4NpDxSz2S .node .label text,#mermaid-svg-oLVm5RK4NpDxSz2S .image-shape .label,#mermaid-svg-oLVm5RK4NpDxSz2S .icon-shape .label{text-anchor:middle;}#mermaid-svg-oLVm5RK4NpDxSz2S .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-oLVm5RK4NpDxSz2S .rough-node .label,#mermaid-svg-oLVm5RK4NpDxSz2S .node .label,#mermaid-svg-oLVm5RK4NpDxSz2S .image-shape .label,#mermaid-svg-oLVm5RK4NpDxSz2S .icon-shape .label{text-align:center;}#mermaid-svg-oLVm5RK4NpDxSz2S .node.clickable{cursor:pointer;}#mermaid-svg-oLVm5RK4NpDxSz2S .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-oLVm5RK4NpDxSz2S .arrowheadPath{fill:#333333;}#mermaid-svg-oLVm5RK4NpDxSz2S .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-oLVm5RK4NpDxSz2S .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-oLVm5RK4NpDxSz2S .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oLVm5RK4NpDxSz2S .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-oLVm5RK4NpDxSz2S .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oLVm5RK4NpDxSz2S .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-oLVm5RK4NpDxSz2S .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-oLVm5RK4NpDxSz2S .cluster text{fill:#333;}#mermaid-svg-oLVm5RK4NpDxSz2S .cluster span{color:#333;}#mermaid-svg-oLVm5RK4NpDxSz2S div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-oLVm5RK4NpDxSz2S .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-oLVm5RK4NpDxSz2S rect.text{fill:none;stroke-width:0;}#mermaid-svg-oLVm5RK4NpDxSz2S .icon-shape,#mermaid-svg-oLVm5RK4NpDxSz2S .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oLVm5RK4NpDxSz2S .icon-shape p,#mermaid-svg-oLVm5RK4NpDxSz2S .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-oLVm5RK4NpDxSz2S .icon-shape .label rect,#mermaid-svg-oLVm5RK4NpDxSz2S .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oLVm5RK4NpDxSz2S .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-oLVm5RK4NpDxSz2S .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-oLVm5RK4NpDxSz2S :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 数据页面

当前版本

SCN=1000
Undo记录1

前镜像

SCN=900
Undo记录2

前镜像

SCN=800
Undo记录3

前镜像

SCN=700
原始值

4.3 可见性判断

#mermaid-svg-UN9XlZT4CHyzmABd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UN9XlZT4CHyzmABd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UN9XlZT4CHyzmABd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UN9XlZT4CHyzmABd .error-icon{fill:#552222;}#mermaid-svg-UN9XlZT4CHyzmABd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UN9XlZT4CHyzmABd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UN9XlZT4CHyzmABd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UN9XlZT4CHyzmABd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UN9XlZT4CHyzmABd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UN9XlZT4CHyzmABd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UN9XlZT4CHyzmABd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UN9XlZT4CHyzmABd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UN9XlZT4CHyzmABd .marker.cross{stroke:#333333;}#mermaid-svg-UN9XlZT4CHyzmABd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UN9XlZT4CHyzmABd p{margin:0;}#mermaid-svg-UN9XlZT4CHyzmABd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UN9XlZT4CHyzmABd .cluster-label text{fill:#333;}#mermaid-svg-UN9XlZT4CHyzmABd .cluster-label span{color:#333;}#mermaid-svg-UN9XlZT4CHyzmABd .cluster-label span p{background-color:transparent;}#mermaid-svg-UN9XlZT4CHyzmABd .label text,#mermaid-svg-UN9XlZT4CHyzmABd span{fill:#333;color:#333;}#mermaid-svg-UN9XlZT4CHyzmABd .node rect,#mermaid-svg-UN9XlZT4CHyzmABd .node circle,#mermaid-svg-UN9XlZT4CHyzmABd .node ellipse,#mermaid-svg-UN9XlZT4CHyzmABd .node polygon,#mermaid-svg-UN9XlZT4CHyzmABd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UN9XlZT4CHyzmABd .rough-node .label text,#mermaid-svg-UN9XlZT4CHyzmABd .node .label text,#mermaid-svg-UN9XlZT4CHyzmABd .image-shape .label,#mermaid-svg-UN9XlZT4CHyzmABd .icon-shape .label{text-anchor:middle;}#mermaid-svg-UN9XlZT4CHyzmABd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UN9XlZT4CHyzmABd .rough-node .label,#mermaid-svg-UN9XlZT4CHyzmABd .node .label,#mermaid-svg-UN9XlZT4CHyzmABd .image-shape .label,#mermaid-svg-UN9XlZT4CHyzmABd .icon-shape .label{text-align:center;}#mermaid-svg-UN9XlZT4CHyzmABd .node.clickable{cursor:pointer;}#mermaid-svg-UN9XlZT4CHyzmABd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UN9XlZT4CHyzmABd .arrowheadPath{fill:#333333;}#mermaid-svg-UN9XlZT4CHyzmABd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UN9XlZT4CHyzmABd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UN9XlZT4CHyzmABd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UN9XlZT4CHyzmABd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UN9XlZT4CHyzmABd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UN9XlZT4CHyzmABd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UN9XlZT4CHyzmABd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UN9XlZT4CHyzmABd .cluster text{fill:#333;}#mermaid-svg-UN9XlZT4CHyzmABd .cluster span{color:#333;}#mermaid-svg-UN9XlZT4CHyzmABd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UN9XlZT4CHyzmABd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UN9XlZT4CHyzmABd rect.text{fill:none;stroke-width:0;}#mermaid-svg-UN9XlZT4CHyzmABd .icon-shape,#mermaid-svg-UN9XlZT4CHyzmABd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UN9XlZT4CHyzmABd .icon-shape p,#mermaid-svg-UN9XlZT4CHyzmABd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UN9XlZT4CHyzmABd .icon-shape .label rect,#mermaid-svg-UN9XlZT4CHyzmABd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UN9XlZT4CHyzmABd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UN9XlZT4CHyzmABd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UN9XlZT4CHyzmABd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否







获取数据行当前版本
ITL.is_active?
事务已提交
是否当前事务修改?
可见
提交SCN ≤ 快照SCN?
沿Undo版本链回溯
找到合适版本?
行不可见

判断规则总结

  1. 自身修改的行始终可见

  2. 已提交且提交 SCN ≤ 快照 SCN 的行可见

  3. 提交 SCN > 快照 SCN 的行需沿 Undo 链回溯

  4. Undo 链耗尽仍找不到合适版本则行不可见

4.4 读视图(ReadView)

  • Read Committed: 每个语句开始时获取新的快照 SCN

  • Serializable: 事务开始时获取快照 SCN,整个事务期间不变

  • Current Committed: 内部使用,略过未提交但最终会提交的行

隔离级别枚举定义:

c 复制代码
typedef enum en_isolation_level {

    ISOLATION_READ_COMMITTED = 1,

    ISOLATION_CURR_COMMITTED = 2,

    ISOLATION_SERIALIZABLE = 3,

} isolation_level_t;

五、ACID 实现机制

详见 文档22

| ACID 特性 | 实现机制 | 关键模块 |

|-----------|----------|----------|

| 原子性(Atomicity) | Undo 回滚:事务失败时通过 Undo 记录逆向恢复数据 | kernel/xact/ |

| 一致性(Consistency) | 约束检查(主键/唯一/外键/CHECK)+ 触发器 | kernel 层面内置支持 |

| 隔离性(Isolation) | MVCC 多版本并发控制 + 行锁/表锁 | 文档25 |

| 持久性(Durability) | Redo 日志 + Checkpoint 检查点 | 文档19 |

原子性实现要点

  • 事务修改数据前先写 Undo 记录

  • Undo 记录包含修改前的完整前镜像

  • ROLLBACK 时按 Undo 链逆序执行回滚

  • 回滚失败会导致数据库宕机(保证一致性)

持久性实现要点

  • 事务提交时必须等待 Redo 日志落盘(WAL 原则)

  • 支持 Group Commit 批量刷盘优化

  • Checkpoint 确保脏页最终持久化到数据文件


六、Undo 段管理

Undo 段是事务回滚和 MVCC 的基础存储结构。详见 文档20

6.1 Undo 段分配

  • 每个实例拥有独立的 Undo 段集合(GS_MAX_UNDO_SEGMENT 个段)

  • 事务启动时从实例的 Undo 段池中分配一个段

  • 段分配策略:轮询/最少使用

  • 段内页面按需扩展

6.2 Undo 记录格式

每个 Undo 记录包含:

  • UNDO_HEADER: 指向上一 Undo 记录的指针(形成版本链)

  • UNDO_DATA: 修改前的列数据(仅修改的列)

  • SSN/SCN: 事务快照序列号/系统变更号

  • 操作类型: INSERT / UPDATE / DELETE

6.3 Undo 回滚

回滚过程:

  1. 定位事务对应的 Undo 段和起始 Undo 页面

  2. 沿 Undo 链正向遍历(从最新到最旧)

  3. 对每条 Undo 记录执行逆向操作(DELETE → INSERT / UPDATE → 旧值覆盖 / INSERT → DELETE)

  4. 释放持有的锁资源

  5. 标记事务槽为已回滚

6.4 Undo 空间回收

  • 事务提交后: Undo 记录不立即回收(供 MVCC 使用)

  • SMON 后台进程: 周期性扫描 Undo 段,回收已提交且不再需要的 Undo 空间

  • Undo 保留期 : 由 undo_retention 参数控制,确保长时间查询能读到一致快照

  • 自动扩展/收缩: Undo 表空间支持自动扩展和手动收缩


七、Savepoint 实现

Savepoint 允许在事务内部设置回滚点:

  • SAVEPOINT name: 记录当前 Undo 位置作为回滚点

  • ROLLBACK TO name: 沿 Undo 链回滚到保存点,丢弃保存点之后的修改

  • RELEASE name: 释放保存点(不执行回滚)

  • 保存点信息存储在事务上下文中,以链表或数组形式管理


八、事务持久化(Transaction 层面的 Redo 写入)

事务的 Redo 写入分为几个层面:

| Redo 类型 | 触发时机 | 说明 |

|-----------|----------|------|

| Undo Redo | 每次 DML 生成 Undo 时 | 保护 Undo 数据不被丢失 |

| Data Redo | 数据页修改时 | 保护数据页变更 |

| Commit Redo | COMMIT 时 | 标记事务已提交,包含 Commit SCN |

| ITL Redo | 事务修改页面时 | 更新 ITL 事务槽信息 |

事务日志写入接口在 knl_xact_log.h 中定义。


九、分布式事务协调(DTC 事务)

在集群环境下,跨节点事务的协调由 DTC 的 dtc_tran.c 模块处理:

  • 全局 SCN 同步: 通过 MES 消息传播 SCN,保持全局有序

  • 跨节点事务查询: 可以通过 DTC 查询其他节点上的事务状态

  • Deposit 事务: 记录节点间的事务依赖关系,用于集群 Recovery

  • XA 两阶段提交 : 支持 XA PREPARE / XA COMMIT / XA ROLLBACK 分布式事务协议

  • pending_trans$: 持久化 PREPARE 状态的事务,保证故障后可恢复

源文件入口:dtc_tran.cknl_xa.h


相关推荐
通问AI1 小时前
Apple Intelligence 国行备案深度技术解析:阿里千问如何被集成到苹果端侧AI架构
人工智能·架构
renhongxia12 小时前
世界模型,是“空中楼阁”还是AGI的“最后一块拼图”?
运维·服务器·数据库·人工智能·算法·agi
程序员无隅2 小时前
Coding Agent 为什么压缩上下文后还能继续工作?上下文模块设计拆解
java·开发语言·数据库
愿做无知一猿2 小时前
Nacos连接MySQL异常?DataGrip竟成救星
数据库·mysql
G.O.G.O.G2 小时前
LeetCode SQL 从入门到精通(MySQL)06(上)
数据库·sql·mysql·leetcode
千桐科技2 小时前
qData 数据中台开源版从 MySQL 到 Doris完成一次数据同步
大数据·mysql·开源·doris·数据中台·qdata
研究员子楚3 小时前
GEO行业发展标准体系白皮书V2.0-第10卷 · 全球篇:跨国标准协同与全球品牌语义治理框架
数据库·人工智能·microsoft·架构·geo
Omics Pro4 小时前
深度学习多组学互作:组内+组间
数据库·人工智能·深度学习·mysql·搜索引擎·自然语言处理
ACP广源盛139246256735 小时前
GSV6155@ACP# 搭配 AI 服务器、AI PC 完整适配方案
大数据·服务器·人工智能·分布式·单片机·嵌入式硬件