\title{数据库事务与工作流编排}
\author{杨岢瑞}
\date{May 28, 2026}
\maketitle
在真实业务场景中，电商下单、跨境支付和供应链协同往往涉及多个服务、多个数据库甚至多个地域的数据操作。传统单体应用里，一次数据库事务就可以用 ACID 保证原子性、一致性、隔离性和持久性；当系统演进为微服务架构后，跨服务的数据孤岛让「瞬间一致性」难以维持。文章的目标正是厘清数据库事务与工作流编排的差异与互补关系，并给出可落地的选型思路。\par
\chapter{数据库事务：从本地 ACID 到分布式事务}
\section{本地事务的 ACID 属性与实现}
本地事务在单机数据库中通过锁、日志与多版本并发控制实现 ACID。原子性依靠预写日志（Write-Ahead Log）在提交前记录所有修改，崩溃后可回滚；一致性由约束检查与触发器保障；隔离性通过锁或 MVCC 版本号避免脏读与幻读；持久性则由刷盘策略决定。以 PostgreSQL 为例，执行\par
\begin{lstlisting}[language=sql]
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
\end{lstlisting}
时，服务器首先在 WAL 中追加两条更新记录，成功刷盘后才修改内存中的页面；若中途宕机，重启后会回放 WAL 完成或回滚事务。\par
\section{分布式事务的必然性与理论基础}
微服务拆分后，订单服务与库存服务各自持有独立数据库，单次 HTTP 调用无法跨越两个本地事务边界。此时 CAP 定理指出，在网络分区存在的情况下，系统只能在一致性与可用性之间二选一；BASE 理论则主张牺牲强一致性，换取高可用与最终一致性。工程上需要在性能、复杂度与一致性等级之间寻找平衡。\par
\section{经典分布式事务模型}
两阶段提交（2PC）引入协调者收集各参与者的投票，决定全局提交或回滚，但协调者单点故障会导致参与者永久阻塞。三阶段提交（3PC）增加超时与预提交阶段以降低阻塞概率，却无法彻底消除。TCC 把业务操作拆成 Try、Confirm、Cancel 三个阶段，由业务层实现补偿逻辑。本地消息表则把跨库消息持久化到与业务表同一事务中，再由定时任务可靠投递，换取最终一致性。\par
\chapter{工作流编排：从「一步」到「多步」的状态机}
\section{工作流核心概念}
工作流把业务流程抽象为任务、状态与转换的集合。任务是原子执行单元，状态记录当前进展，转换由事件或条件驱动。多个任务通过有向无环图组织，形成显式的依赖与并行关系；状态机则在运行时维护状态流转，保证同一业务实例不会重复执行或遗漏步骤。\par
\section{工作流引擎的分类与选型}
轻量级引擎如 Temporal 把工作流定义为普通代码，支持强类型与本地调试；重量级引擎如 Camunda 提供可视化建模与持久化状态存储，适合长周期审批流程；云原生方案如 AWS Step Functions 把状态机托管在云端，按调用次数计费。选型时需评估团队对状态机与事件驱动的熟悉程度，以及对可视化与运维成本的接受度。\par
\section{工作流与数据库事务的边界与互补}
数据库事务负责「瞬间一致性」，确保单次操作的 ACID；工作流负责「业务一致性」，跨越多个事务边界并在失败时触发补偿。二者并非互斥，工作流可以启动本地事务，也可以在事务失败后调用补偿服务。\par
\chapter{Saga 模式：把长事务拆成短事务}
\section{Saga 的起源与定义}
Saga 把原本需要长时间持锁的长事务拆成一系列本地 ACID 短事务，每个短事务提交后立即释放资源，全局层面仅保证 BASE 语义。局部失败时，通过反向补偿操作回滚已完成的前序步骤。\par
\section{协同式与编排式 Saga}
协同式 Saga 依赖事件总线，各服务监听上游事件并自主决定下一步，耦合度低但调用链难以观测。编排式 Saga 引入中心协调器，显式描述任务依赖与重试策略，适合需要人工干预或复杂分支的场景。\par
\section{补偿设计要点}
补偿操作必须满足幂等性，避免同一消息被处理多次导致重复扣款；同时需记录正向与反向操作的配对关系，例如「扣库存」对应「加库存」。在实现时，可为每笔业务请求生成全局唯一 Token，写入数据库唯一索引，防止并发重试。\par
\section{异常处理策略}
当 Saga 执行到一半失败时，可选择全量回滚、部分成功并人工兜底，或仅对关键路径回滚。策略选择取决于失败代价与业务可接受的不一致窗口。\par
\chapter{现代工作流引擎与数据库事务的协同}
\section{持久化执行状态}
工作流引擎需持久化状态以支持故障恢复与人工干预。事件溯源把每次状态变更作为不可变事件追加到日志，通过重建状态机恢复现场；快照则定期固化当前状态，减少回放开销。存储介质可选用关系型数据库、专用 Workflow Store 或具备强一致性的 NoSQL。\par
\section{事务边界划分与资源预留}
在 Saga 中，每个本地事务应尽量短小，称为微事务。资源预留阶段先扣减可用额度，确认阶段再真正扣款；若后续步骤失败，预留资源可被释放或超时作废，避免长时间占用。\par
\section{一致性保障技术}
幂等 Token、分布式锁与乐观锁版本号是常用手段。死信队列收集多次重试仍失败的消息，供人工或补偿脚本处理。定时重试需结合指数退避，防止雪崩。\par
\section{可观测性与可运维}
TraceID 应贯穿数据库事务与工作流调用链，实现全链路追踪。状态机可视化可实时展示当前节点，断点调试允许在特定步骤暂停以注入故障；人工干预接口则可在异常场景下手动推进或回滚。\par
\chapter{实战案例拆解}
\section{电商下单全链路}
以「下单→支付→库存→物流」为例，订单服务在本地事务中写入订单与支付流水；工作流引擎启动后依次调用支付、库存与物流服务。若库存扣减失败，工作流触发支付退款与订单状态回滚，所有补偿操作均通过 Saga 协调器记录执行结果。\par
\section{SaaS 多租户初始化}
租户开通时需初始化分片数据库、写入权限表并订阅消息队列。Temporal 工作流把这些步骤编排为代码，可在任意节点失败后从断点继续，保证「最多一次」或「最少一次」语义，避免重复初始化。\par
\section{金融 T+1 清算}
清算作业通常以批处理形式运行，Saga 把总账拆分为多个并行分片，每个分片独立提交本地事务。最终一致性允许部分分片延迟完成，但全局余额在 T+1 日结束前必须平衡。\par
\chapter{选型与设计 checklist}
在选型时，首先明确一致性要求：强一致适合金融核心账务，最终一致适合营销活动，人工兜底适合长周期审批。接着评估失败代价，若数据不一致窗口不可接受，则需引入更强的协调机制。团队对状态机与事件驱动的熟悉程度直接影响落地难度；可视化、监控与回滚脚本的运维成本也需纳入考量。最后检查生态集成，例如是否已使用 Kafka、gRPC 或云函数。\par
\chapter{未来趋势}
Workflow as Code 把工作流逻辑写成普通程序，Temporal 与 Durable Functions 是典型代表。数据库内置工作流能力也在演进，PostgreSQL 结合 JSON Schema 可在触发器中实现简单状态机，MySQL 8.0 的窗口函数则方便批处理场景下的状态计算。AI 辅助补偿决策可基于历史 Trace 自动生成 Saga 脚本，CNCF Serverless Workflow 规范则试图统一云端工作流描述语言。\par
数据库事务解决「瞬间一致性」，工作流编排解决「跨时态一致性」。二者并非互斥，而是不同抽象层次的工具；合理组合才能构建高可用的业务系统。\par
