事务管理架构
阅读时间: 约 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版本链回溯
找到合适版本?
行不可见
判断规则总结:
-
自身修改的行始终可见
-
已提交且提交 SCN ≤ 快照 SCN 的行可见
-
提交 SCN > 快照 SCN 的行需沿 Undo 链回溯
-
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 回滚
回滚过程:
-
定位事务对应的 Undo 段和起始 Undo 页面
-
沿 Undo 链正向遍历(从最新到最旧)
-
对每条 Undo 记录执行逆向操作(DELETE → INSERT / UPDATE → 旧值覆盖 / INSERT → DELETE)
-
释放持有的锁资源
-
标记事务槽为已回滚
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.c、knl_xa.h