Oracle必须用XA模式而非AT模式,因AT依赖SQL解析与undo_log自动管理,而Oracle不支持该机制;强行启用会导致分支注册成功但全局提交卡死在PhaseOne,且ojdbc8+驱动对SQL拦截敏感易引发协议异常,XA模式则交由Oracle自身XA实现保障事务可靠性。

Seata 默认的 AT 模式不支持 Oracle,必须强制切换为 XA 模式,否则 GlobalTransaction 会静默失败或抛出 XAException,且日志几乎不暴露根本原因。
为什么 Oracle 必须用 XA 模式而不是 AT 模式
Oracle 的 AT 模式依赖数据库层解析 SQL 并自动生成 undo_log 表回滚快照,但 Oracle 不支持该机制——它没有标准的 SELECT FOR UPDATE + INSERT INTO undo_log 的兼容路径。强行启用会导致分支事务注册成功、全局提交卡死在 PhaseOne,现象是服务无响应、TC 日志停在“branch register success”后不再推进。
-
AT模式下 Seata 会尝试拦截并重写 SQL,Oracle 驱动(尤其是 ojdbc8+)对此行为敏感,容易触发协议异常或隐式连接关闭 -
XA模式把事务控制权交还给 Oracle 自身的 XA 实现,由OracleXADataSource和底层XAResource协同完成两阶段提交,这是唯一被 Oracle 官方验证的分布式事务路径 - Spring Boot 3.x 中
spring-boot-starter-jdbc的自动配置会覆盖 XA 数据源初始化逻辑,必须显式禁用
Oracle XA 数据源配置的关键点
错配驱动与 XA 实现类是最常见的“连得上但事务失败”原因。Oracle 12c/19c/21c 对 XAResource 接口的支持细节不同,不能混用。
- 必须使用
ojdbc8.jar(对应 Oracle 12.1+),搭配oracle.jdbc.xa.client.OracleXADataSource;ojdbc6.jar未实现XAResource,RM 注册直接失败 - 数据源配置中
url必须含tns_alias或完整jdbc:oracle:thin:@//host:port/service_name格式,不能用旧式:@host:port:sid,否则 XA 连接无法识别为XA-capable - Spring Boot 应用需排除自动配置:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - 应用级配置明确指定模式:
seata.data-source-proxy-mode: XA(注意不是AT,也不是空值)
Oracle 数据库端必须开启 XA 支持
Java 层配置全对,Oracle 实例若未启用 XA,连接会在 prepare 阶段直接拒绝,错误日志仅显示 java.sql.SQLException: Protocol violation,毫无线索。
- 执行
ALTER SYSTEM SET "_xa_roundtrip_optimization"=false SCOPE=BOTH;(Oracle 12c+ 必须关闭,否则 XA 分支prepare失败) - 授予用户必要权限:
GRANT SELECT ON sys.dba_pending_transactions TO your_user;、GRANT SELECT ON sys.pending_trans$ TO your_user;、GRANT XA_RECOVER_ADMIN TO your_user; - 验证是否生效:
SELECT * FROM V$XATRANS;应返回空结果集(表示 XA 功能就绪,非报错)
Seata TC 和 RM 的配套调整
只改数据源类型远远不够。TC 若仍按 AT 模式解析 SQL,会尝试生成不存在的 undo_log,导致分支注册后无法推进。
-
file.conf中store.mode="db"保持不变(XA 模式仍需 TC 存储事务状态),但db.dbType必须设为"oracle",且 URL、账号密码要匹配 Oracle 实例 -
service.vgroupMapping.my_test_tx_group="default"必须与应用侧@GlobalTransactional的value一致,否则 TC 找不到对应事务分组 -
client.rm.report.success.enable=false:Oracle XA 分支的commit/rollback由数据库自身驱动完成,RM 不应上报“成功”,否则 TC 可能提前释放XID锁 - 确认
registry.conf和file.conf中未残留undo_log相关表名配置(如globalTable等字段在 XA 模式下已失效)
最易被忽略的是 Oracle 端的 "_xa_roundtrip_optimization" 参数和驱动版本绑定——这两个点不出问题时一切正常,一出就是 XAER_RMFAIL 或静默挂起,查日志根本看不出和 XA 有关。


















