公司要装修新办公室,项目经理老张同时管着电工队、木工队和油漆队。三支队伍必须同一天进场,因为电路改造、木工隔断和墙面漆互相依赖——先刷墙再走线,就是灾难。于是老张定了个规矩:开工前一天,每支队伍先到仓库把材料备好锁起来,向老张汇报「材料齐了,随时能开工」;等三支队伍全部汇报完毕,老张再统一通知「明天早上八点,正式开工」。如果有一支队伍说「材料缺货」,老张就宣布「取消项目,各队处理掉备好的材料」。这套「先备料、再统一开工」的流程,就是分布式事务中著名的两阶段提交。XA 协议,正是把这种朴素的协作直觉固化为跨行业标准接口的规范。

岗位关联

掌握 XA 协议,能让你在面对跨库事务一致性、微服务数据拆分等真实架构问题时,快速判断「该不该用强一致」「瓶颈在哪」「如何降级」,这是从「会写增删改查」走向「能设计可靠系统」的关键一步。

目录
  1. 可视化演示
  2. 分布式事务背景:一个人的饭局与一群人的宴席
  3. 核心角色分工:项目经理、施工队与客户
  4. 两阶段提交流程:先备料,再统一开工
  5. 全局锁与阻塞:锁在仓库里的材料
  6. 性能与可用性缺陷:老张失联与交错的开工时间
  7. 工程优化手段:给项目装上保险丝
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

演示 XA 协议基于两阶段提交规范协调异构资源管理器,步进切换查看 TM 与 RM 的 prepare/commit 交互流程、阻塞问题与工程优化手段,理解分布式事务的协调机制。

本节配有交互动效(进入视口后自动加载,约 3KB)。

XA 两阶段提交 TM 协调 RM 执行两阶段提交 prepare 阶段锁定资源 commit 阶段统一提交 一致性 = 全体提交 协调失败会引发阻塞问题

分布式事务背景:一个人的饭局与一群人的宴席

周末自己做饭,一切尽在掌握——菜炒糊了倒掉重来,盐放多了加点水,所有决定都是一瞬间的事。但如果公司要办一场大型团建宴席,你一个人说了不算:需要川菜馆出热菜、烘焙坊出甜品、水果商送果盘。任何一家掉链子,整场宴席就得重新安排。这个从「一个人」到「一群人」的变化,正是分布式事务要解决的难题。

数据库的发展轨迹与之完全吻合。早期的单机数据库就像一个人做饭:一个事务要么全部生效(commit),要么全部回滚(rollback),这就是 ACID 的原子性。可当业务量上来,数据要从一个库拆到多个库——订单库、库存库、账户库各管一摊,一次下单操作要同时改两个甚至三个库,而每个库各自的本地事务只能保证自己那摊的成败。一旦中间某一步失败,整笔订单就会变成「库存扣了、订单没建」的烂账。

这时候就需要一个「总协调者」,把多个数据库的本地事务统一纳入一个全局事务。XA 协议(eXtended Architecture)正是 X/Open 组织制定的分布式事务处理规范,它定义了全局事务的接口和两阶段提交的交互流程,让异构的数据库(比如 MySQL 和 Oracle 混用)也能被同一个事务管理器统一协调。数据拆得越碎、系统越分布式,这种「全局统一」的需求就越强烈——这既是分布式系统发展的必然,也是它最棘手的挑战之一。

「先备料、再统一开工」这个朴素的直觉,就是分布式事务最核心的解题思路。明白了为什么多家店铺必须一起合作,才能理解接下来谁负责协调、谁负责执行、走什么流程。

核心角色分工:项目经理、施工队与客户

回到装修办公室的项目。整个工程有三个角色:提出需求的客户(老板),统筹全局的项目经理老张,和实际干活的电工、木工、油漆三支施工队。客户说「我要一个现代化办公室」,老张负责把需求拆解成施工计划,施工队负责在各自的领域落地。没有清晰的角色分离,这个项目很快会乱成一锅粥。

XA 协议也把参与者分成三个角色。Application Program(AP,应用程序)是发起全局事务的客户;Transaction Manager(TM,事务管理器)是全局协调者,负责决定事务提交还是回滚;Resource Manager(RM,资源管理器)是真正管理数据资源的组件,数据库就是最常见的 RM。一个 RM 管理一个局部数据资源,多个 RM 共同构成全局事务的数据面。

三个角色之间有标准的交互接口。AP 通过 TM 的接口开启全局事务(xa_start)、结束全局事务(xa_end)、提交事务(xa_commit)或回滚(xa_rollback)。RM 需要实现 prepare、commit、rollback 等回调,供 TM 调用。这套接口由 X/Open 定义,任何遵循规范的数据库、消息队列都可以接入,这就是「异构资源」能被统一协调的底层原因。用 MySQL 社区版加 Oracle 企业版同时参与一个全局事务,在今天已经不是天方夜谭。

客户不用知道老张怎么跟施工队沟通细节,他只需说「开始吧」或「停吧」。同样,AP 只需要跟 TM 打交道,TM 再去逐一指挥 RM。角色分离让复杂的分布式协调变成清晰的层级结构——这也是 XA 被誉为「分布式事务里程碑」的原因。

两阶段提交流程:先备料,再统一开工

老张的管理动作可以拆成两步。第一步「备料确认」:他通知电工队、木工队、油漆队把各自需要的材料搬到仓库,锁进专属货架,然后向老张汇报「材料齐了」。第二步「统一开工」:老张确认三队都就绪后,在早晨八点统一喊「开工」,三队同时进场施工。如果哪一队汇报「砂石缺货」,老张立刻喊停,让已备料的队伍把材料退回供应商,取消整个工程。

这就是两阶段提交(Two-Phase Commit,2PC)的直观样子。第一阶段叫 prepare(准备):TM 向所有 RM 发送 prepare 请求,RM 执行本地事务写入并锁定资源,但先不提交,只返回「就绪(ready)」或「未就绪(abort)」。此时本地事务的数据修改对其它事务不可见,锁却被真实持有——这正是「备好材料锁进仓库」的数据库版。

第二阶段叫 commit(提交或回滚)。如果 TM 收到所有 RM 的「就绪」,就向所有 RM 发送 commit 指令,各 RM 真正落盘提交。如果任一 RM 返回「未就绪」或超时未响应,TM 就向所有 RM 发送 rollback 指令,各 RM 撤销本地修改。这里的关键是「全局一票否决」:只要有一个 RM 不能提交,整个全局事务就回滚。

Psuccess=∏i=1npi\displaystyle P_{\text{success}} = \prod_{i=1}^{n} p_i

1. 单节点成功率 $p_i$:表示第 $i$ 个 RM 在执行 prepare 时不出错、能正常锁定资源的概率。如果某个数据库磁盘故障,这个值就会变小。

pi∈(0,1]p_i \in (0, 1]

2. 连乘符号 $\prod$:把 $n$ 个 RM 的成功率逐个相乘。每乘一个小于 1 的数,结果就会变小一次。

∏i=1npi=p1×p2×⋯×pn\prod_{i=1}^{n} p_i = p_1 \times p_2 \times \cdots \times p_n

3. 节点数量 $n$:参与全局事务的 RM 总数。$n$ 越大,乘积项越多,全局成功率下降得越快。

n→∞⇒Psuccess→0n \to \infty \Rightarrow P_{\text{success}} \to 0

4. 全局成功率含义:只有所有 RM 都成功,全局事务才成功,所以全局成功率是各节点成功率的乘积;任何一个环节失败,全局事务都会回滚。

∃i, pi=0⇒Psuccess=0\exists i,\ p_i = 0 \Rightarrow P_{\text{success}} = 0

三支施工队每队不出岔子的概率如果是 90%,三队同时不出岔子的概率就只有 72.9%。老张把越来越多的队伍拉进同一个工程时,工程「一次性顺利完工」的可能性会被快速稀释。这正是两阶段提交在工程上最让人头疼的地方——节点越多,越容易翻车。

全局锁与阻塞:锁在仓库里的材料

备料确认这个动作有个隐藏代价:材料一锁进仓库货架,施工队就不能把材料挪去做别的项目。老张迟迟不下「开工」令,材料就一直锁在货架上。这段等待时间里,施工队虽然什么都没干,但仓库空间、材料资源全被占用,其他项目想用这批货架也进不来。

XA 的 prepare 阶段同样有「锁材料」的代价。RM 在执行完本地事务的数据修改后,必须持有行级锁或表级锁直至收到 TM 的最终指令。这就意味着 prepare 完成但 commit 未到时,被修改的数据不能被其他事务读写,这就是全局锁带来的读/写阻塞。表面上数据还是「可恢复的中间态」,实际上它已经被单方面占用了。

全局锁带来的直接后果是阻塞。一个 RM 准备好之后,如果网络延迟、TM 负载高,它就要一直等。等的时间越长,这个数据库上其他事务排队越长,系统吞吐量直线下降。更极端的情况是事务之间互相等待彼此持有的锁,形成死锁——虽然数据库有死锁检测,但超时前的等待窗口依然真实存在。

Tblock=Tprepare+Thold\displaystyle T_{\text{block}} = T_{\text{prepare}} + T_{\text{hold}}

1. 准备耗时 $T_{\text{prepare}}$:TM 发出 prepare 请求到收到所有 RM 响应之间的时间,包括网络往返和 RM 本地写日志的开销。

Tprepare=Tnet+TdiskT_{\text{prepare}} = T_{\text{net}} + T_{\text{disk}}

2. 持有等待 $T_{\text{hold}}$:所有 RM 完成 prepare 后,资源进入锁定状态,直到某个 RM 收到 commit 或 rollback 指令的那一刻为止。

Thold=Twait_decisionT_{\text{hold}} = T_{\text{wait\_decision}}

3. 总阻塞时长:两者相加即为资源被锁定的总时间。任一项变大,下游事务的排队时间都会同步变长,系统吞吐随之下降。

Tblock↑⇒吞吐量↓T_{\text{block}} \uparrow \Rightarrow \text{吞吐量} \downarrow

材料锁在仓库一天,施工队的产能就浪费一天。老张如果迟迟不给指令,不仅三支施工队开不了工,连其他项目的材料都没处放。这就是为什么 XA 事务要求「短、平、快」——事务执行时间越长,阻塞成本越高。

性能与可用性缺陷:老张失联与交错的开工时间

老张的第二个潜在麻烦是:他是整个项目的唯一决策人。如果他在三支施工队都备好料之后突然失联(手机没电、出差关机),施工队既不敢开工——也许老张要取消项目,也不敢撤料——也许老张马上要开工,只能原地待命。只有老张回来,项目才能重新动起来。

映射到系统里就是「协调者单点问题」。TM 是全局事务唯一的决策点,一旦 TM 宕机且没有高可用机制,所有已 prepare 但未 commit 的 RM 都会停留在锁定状态,无从得知该提交还是回滚。数据不会损坏,但整个业务会停摆,直到 TM 恢复。这直接违背了分布式系统对「可用性」的期待。

另一个真正的硬伤是「不一致窗口」。即使 TM 完美地依次发出 commit 指令,网络传输和各个数据库提交耗时不同,RM1 可能 10ms 就提交完成,RM3 却要 500ms 才提交完成。在这 490ms 内,外部应用读到 RM1 已经写入的新数据,而 RM3 还是旧数据——全局视图是不一致的。XA 的强一致只是「最终在提交完成后一致」,提交过程中有短暂的不一致窗口。

ΔTwindow=tlast−tfirst\displaystyle \Delta T_{\text{window}} = t_{\text{last}} - t_{\text{first}}

1. 最先完成时刻 $t_{\text{first}}$:第一个 RM 真正落盘并返回提交成功的时间点,是所有 RM 提交耗时中最小的那个。

tfirst=min⁡iti, i=1,…,nt_{\text{first}} = \min_i t_i,\ i=1,\dots,n

2. 最后完成时刻 $t_{\text{last}}$:最后一个 RM 提交成功的时间点,是所有 RM 提交耗时中最大的那个。

tlast=max⁡iti, i=1,…,nt_{\text{last}} = \max_i t_i,\ i=1,\dots,n

3. 窗口差值 $\Delta T_{\text{window}}$:两者相减得到不一致窗口的时长。窗口内不同 RM 上的数据版本不一致,可能被外部读取到。

ΔTwindow>0⇒存在不一致读取\Delta T_{\text{window}} > 0 \Rightarrow \text{存在不一致读取}

三支施工队虽然收到的是同一句「开工」,但有的队动作快、有的队磨蹭,场面上的施工进度必然有先有后。老张唯一能承诺的是「大家最终都会完工」,但不可能承诺「任何一秒看过去都干得一样快」。理解了这个窗口,你就能明白为什么很多系统宁可用最终一致性方案,也不愿扛住 XA 的这些代价。

工程优化手段:给项目装上保险丝

经验丰富的老张后来学聪明了。他给备料环节加了「超时熔断」:如果某队 2 小时内没汇报,就取消项目,让其他队伍释放材料。他还准备了「应急预案」:某队实在来不了,就临时改成先让其他队干,缺的活儿后补,反正最后整体能交付。

工程化的 XA 优化思路与此同频。第一招是超时与重试:TM 给 prepare 和 commit 都设置超时,超时未收到响应就按失败处理,触发回滚或重试,避免 RM 无限期锁资源。同时 TM 自身可以做成集群并持久化事务日志,主 TM 宕机后由备 TM 接管,缓解单点问题——这就是给项目经理配一个备用手机。

第二招是降级为本地消息表加消息队列:业务在同一数据库中同时写业务数据和一条「待发送消息」,利用本地事务保证二者原子;然后通过消息队列异步通知其他服务消费。这一步放弃了 XA 的全局强一致,换取可用性和吞吐。第三招是业务设计规避:比如把「扣库存」从下单的同步链路里拆出去,用预占、超时释放、异步对账来兜底,让核心链路根本不需要跨库事务。在真实生产环境里,这两种「妥协」比硬扛 XA 常见得多——这正是「最终一致性」思想落地的典型路径。

聪明的项目经理不会把宝全押在「三队必须同时开工」这一条路上。能并联的活就并联,不能保证的环节就设计退路,最终交付才是目标——分布式系统设计里的「降级优先」哲学,本质上就是这种务实精神的技术化表达。

AI 应用场景

金融核心账务系统的强一致保障

阶段:AI 系统数据基础设施层

解决的问题:AI 风控模型识别出高风险转账后,系统需要同时冻结付款方余额、写入转账流水并在收款方账户做待入账标记——这三个动作分布在不同库。传统做法先改付款库再改流水库,中间一旦宕机,资金状态就乱了。XA 全局事务可以保证三库「同生共死」,任何一库失败则全部回滚。

具体案例:某银行核心账务系统在夜间批量代发工资场景中,一个批次涉及数万个账户的扣款与入账,被拆分成多个 XA 短事务(每个事务只处理几百个账户),配合 TM 集群与超时重试,将单批次处理时间控制在秒级,同时保证跨账户的余额强一致。

电商微服务订单链路的取舍

阶段:业务中台数据同步层

解决的问题:基于用户画像的秒杀活动带来瞬间高并发,订单服务、库存服务、支付服务各自独立数据库。若用 XA 强一致,库存行被长事务锁住,秒杀直接变成「秒没」。于是改为「本地消息表 + 消息队列」的最终一致性方案,用吞吐换强一致。

具体案例:某电商平台将「下单减库存」从同步链路改为异步预占:订单库写入订单记录和「待扣减库存」消息(同一本地事务),消息队列消费后异步扣减库存,失败则定时任务补偿对账。降级后吞吐提升了一个数量级,数据在 1 秒内达到最终一致。

分布式数据库内核的跨节点事务

阶段:存储引擎事务层

解决的问题:AI 训练样本数据分布在多个存储节点,单条 SQL 的执行计划可能跨三个节点。分布式数据库在内部实现类似 XA 的两阶段提交,对上层应用透明,让 AI 工程师像用单机数据库一样使用分布式存储。

具体案例:某 NewSQL 数据库将数据按主键范围分片,每个分片由一个 Raft 组管理。跨分片事务的协调者扮演 TM 角色,分片扮演 RM 角色,用两阶段提交保证多分片写入的原子性,同时通过分片迁移与 Raft 高可用弱化单点风险。

Python 演示

python64 行
"""XA 两阶段提交协议的简化模拟器"""import randomimport time  class ResourceManager:    """资源管理器 RM: 模拟一个参与全局事务的数据库节点"""     def __init__(self, name):        self.name = name        self.ready = False        self.committed = False     def prepare(self):        """第一阶段: 锁定资源并返回是否就绪"""        time.sleep(0.05)        self.ready = random.random() > 0.2        return self.ready     def commit(self):        """第二阶段: 正式提交本地事务"""        time.sleep(0.05)        self.committed = self.ready        return self.committed     def rollback(self):        """回滚: 撤销本地修改并释放锁"""        self.ready = False        self.committed = False  class TransactionManager:    """事务管理器 TM: 模拟 XA 全局协调者"""     def __init__(self, rms):        self.rm_list = rms        self.state = "IDLE"     def run(self):        """执行两阶段提交的完整流程"""        self.state = "PREPARE"        prepared = [rm.prepare() for rm in self.rm_list]         if all(prepared):            self.state = "COMMIT"            for rm in self.rm_list:                rm.commit()            self.state = "COMMITTED"            return "SUCCESS"         self.state = "ROLLBACK"        for rm in self.rm_list:            rm.rollback()        self.state = "ABORTED"        return "ABORT"  if __name__ == "__main__":    rms = [ResourceManager("订单库"), ResourceManager("库存库"), ResourceManager("账户库")]    tm = TransactionManager(rms)    result = tm.run()    print("全局事务结果:", result)    for rm in rms:        print(f"{rm.name}: ready={rm.ready}, committed={rm.committed}")
目的:模拟一个 TM 协同三个 RM 执行 XA 两阶段提交的完整流程,观察全部成功与任一失败时的全局结果差异。
  1. self.ready = random.random() > 0.2以 80% 概率模拟 RM 在 prepare 阶段成功,复现「单节点成功率 pᵢ」的概念
  2. prepared = [rm.prepare() for rm in self.rm_list]TM 向所有 RM 发起 prepare 请求,对应两阶段提交的第一阶段
  3. if all(prepared):全局一票否决:只有所有 RM 都返回就绪,全局事务才允许进入提交阶段
  4. for rm in self.rm_list: rm.commit()第二阶段统一下达 commit 指令,各 RM 真正落盘提交
  5. for rm in self.rm_list: rm.rollback()任一 RM 未就绪则全体回滚,与 commit 分支互斥

常见误区

误区我以为 XA 协议和两阶段提交(2PC)是同一个东西,学会了 2PC 的流程就等于掌握了 XA,面试时把两者混着说也完全没问题。

正解两阶段提交是一种分布式算法思想,描述「怎么分两步完成协调」;XA 是 X/Open 组织基于 2PC 制定的接口规范,规定「谁调用谁、传什么消息、返回什么状态」。就像装修的「开工流程」和「施工合同」是两回事——前者是步骤,后者是各方必须遵守的约定条款。规范还包括 xa_start、xa_end、xa_prepare 等具体接口定义。

为何常见:两者概念高度重合,教材常说「XA 基于两阶段提交」,初学者很容易把「基于」理解成「等于」,于是把流程本身当成了全部规范。

误区只要所有 RM 都返回了「就绪」,我就认为这单事务已经成功了,数据一定会一致,可以放心地给用户弹「操作成功」。

正解prepare 全部成功只是进入提交阶段的「入场券」,不是结果。提交阶段仍可能因网络分区、协调者崩溃、RM 故障而中断,导致部分 RM 已提交、部分未提交。就像施工队备好料并不等于房子已经装完——真正动工后仍可能出状况。

为何常见:把「消息返回成功」等同于「数据已固定落盘」,忽略了 commit 指令本身也可能在传输中丢失,这是对异步系统的常见误判。

误区既然 XA 能保证强一致,那高并发业务也用 XA 最稳妥,大不了多买点数据库性能,反正「一致性」一定是第一位的。

正解XA 的同步阻塞和资源锁定让它的吞吐率天然偏低,prepare 后持有的锁会让其他事务长时间排队。它适合低并发、强一致、短事务的场景(如金融转账);高并发秒杀、大规模写入场景下,应该考虑本地消息表、TCC、Saga 等最终一致性方案。

为何常见:思维上把「正确性」等同于「性能」,忽视了事务的强一致性本质上是用并发度换来的——锁不释放,别人就只能等。

误区用了 XA 就万事大吉,任何时刻去任何 RM 上查数据,结果都应该是一样的,不然怎么叫「强一致」呢?

正解XA 只能保证提交前后的事务原子性,但 commit 过程本身是异步的,从第一个 RM 到最后一个 RM 提交完成的窗口内,各节点的数据版本并不一致。外部应用仍可能读到「部分新、部分旧」的数据,只是这个窗口通常很短。

为何常见:教科书常画「瞬间完成」的时序图,省略了网络传输和磁盘刷盘的真实耗时,给学生造成了「提交是一瞬间」的错觉。

面试题

Q1. XA 协议中,事务管理器(TM)的核心职责是什么?

单选题 · easy

  • A.执行具体 SQL 操作
  • B.协调事务提交回滚← 正确答案
  • C.管理数据库的索引
  • D.存储应用业务数据

答案:B。TM 相当于装修项目的项目经理,只做「全局决策」,不碰具体数据。执行 SQL、管理索引、存储数据都是 RM 或 AP 的职责,只有「协调全局事务的提交与回滚」才是 TM 的核心工作。

Q2. 在 prepare 阶段,资源管理器(RM)具体做什么?

单选题 · easy

  • A.立即提交本地事务
  • B.锁定资源并返回就绪← 正确答案
  • C.释放所有锁定的资源
  • D.回滚并通知协调者

答案:B。prepare 阶段 RM 执行本地事务的数据修改、锁定资源,但不提交,只返回「就绪」或「未就绪」。就像施工队把材料锁进仓库后向老张汇报「备齐了」,此时既不施工(提交)也不退场(回滚)。

Q3. 为什么 XA 的全局成功率会随 RM 节点数增加而下降?

单选题 · mid

  • A.各节点成功率乘积效应← 正确答案
  • B.各节点失败率加法效应
  • C.事务管理器随机地失败
  • D.SQL 查询数量不断增多

答案:A。全局成功率等于各 RM prepare 成功率的乘积,每多一个节点就多乘一个小于 1 的数,整体成功概率快速下降。不是失败率相加、不是 TM 随机失败,而是「一票否决」带来的乘积效应。

Q4. 以下哪个场景最能体现 XA 的阻塞问题?

单选题 · mid

  • A.锁资源等协调者指令← 正确答案
  • B.事务管理器做磁盘备份
  • C.数据库周期性清理日志
  • D.应用服务器突发地宕机

答案:A。prepare 完成后 RM 持有锁、等待 TM 最终指令,是最典型的阻塞场景——材料锁在仓库里等老张下指令。TM 做备份、数据库清日志、应用宕机都不是协议层面的阻塞特征。

Q5. XA 协议的固有缺陷包括以下哪些?

多选题 · mid

  • A.同步阻塞降低性能指标← 正确答案
  • B.协调者单点故障风险← 正确答案
  • C.提交阶段存在不一致窗口← 正确答案
  • D.完全无法处理回滚场景

答案:ABC。同步阻塞、协调者单点、提交阶段的不一致窗口是 XA 三大固有缺陷。D 错误——XA 内置了完整的 rollback 分支,「一票否决」后的全局回滚正是它的核心能力。

Q6. TM 在 prepare 全部成功后、commit 发送中宕机,各 RM 会发生什么?

单选题 · hard

  • A.所有 RM 自动回滚事务
  • B.RM 保持就绪等待恢复← 正确答案
  • C.所有 RM 立即自动提交
  • D.数据立刻产生不一致

答案:B。RM 处于「已就绪但不知道最终决策」的状态,只能保持锁定等待 TM 恢复。自动回滚、自动提交都是错的,因为协议规定 RM 不可以自行猜测决策;数据不会立刻不一致,但业务会陷入长时间阻塞。

Q7. 生产环境中降低 XA 阻塞损失的工程手段包括哪些?

多选题 · hard

  • A.引入超时机制释放资源← 正确答案
  • B.本地消息表最终一致性← 正确答案
  • C.使用补偿机制替代强一致← 正确答案
  • D.彻底取消全部分布式事务

答案:ABC。超时释放资源、本地消息表降级、补偿机制替代,都是真实生产里常见的优化手段。D 不现实——业务的一致性需求还在,只是换一种方案去实现,而不是直接取消。

Q8. 以下哪类业务最适合使用 XA 协议?

单选题 · easy

  • A.高并发互联网秒杀场景
  • B.强一致短期金融转账事务← 正确答案
  • C.离线大数据批量分析
  • D.热点缓存失效更新

答案:B。XA 适合低并发、强一致、短事务的场景,金融转账正是典型代表。秒杀追求高吞吐,大数据分析和缓存更新不需要跨库强一致,它们都应该考虑最终一致性方案。

Q9. 什么是 XA 中的「协调者单点」问题?

单选题 · mid

  • A.多个协调者组成集群来决策
  • B.全局唯一 TM 故障致停滞← 正确答案
  • C.每个 RM 自行独立提交事务
  • D.数据库主从节点自动切换

答案:B。全局只有一个 TM 做决策,它一故障,所有已 prepare 的 RM 就陷入阻塞等待,这是 XA 可用性缺陷的核心。多个协调者集群、RM 独立决策、主从切换都不是对「单点」的描述。

Q10. RM 在 prepare 成功、commit 前崩溃,恢复后应该如何做?

单选题 · hard

  • A.自动提交未完成的本地事务
  • B.询问 TM 决策后执行对应动作← 正确答案
  • C.永久保持资源锁定不释放
  • D.重启后自动执行回滚操作

答案:B。RM 恢复后必须向 TM 询问该全局事务的最终决策(commit 还是 rollback),然后执行。自动提交、永久锁定、重启即回滚都违反了「决策权在 TM」的协议设计——就像施工队恢复联系后要先问老张「这项目还干不干」。