seata-go支持at与tcc模式,但非开箱即用:at需代理数据源、启用binlog、建undo_log表且不支持复合sql;tcc需手动实现try/confirm/cancel及空补偿、防悬挂;两者均需显式处理xid透传与vgroup-mapping配置。

Seata-Go 能用,但不是“开箱即用”的黑盒,它要求你明确选择事务模式、手动注入代理逻辑、并处理跨服务的 XID 透传——AT 模式最省事,TCC 模式更可控,但两者都绕不开对业务代码的侵入性改造。
AT 模式接入:代理数据源 + 自动 undolog 是关键
AT 模式依赖 Seata 对 SQL 执行的拦截和 undo log 自动生成,所以必须用 datasource.NewDataSource() 包装原始数据库连接,而不是直接使用 sql.Open()。否则事务回滚会失效,且不会报错,只默默跳过补偿逻辑。
- MySQL 必须开启 binlog(
binlog_format=ROW),否则无法解析 SQL 变更生成 undo log - 建表语句里要包含
undo_log表(Seata 提供 DDL 脚本),否则分支事务注册成功但回滚时找不到日志表 - 不支持
INSERT ... ON DUPLICATE KEY UPDATE这类复合语句的自动补偿,需降级为 TCC 或手动处理 -
Begin()后的 DB 操作必须在同一个 goroutine 内完成,跨 goroutine 会丢失上下文导致 XID 为空
TCC 模式接入:空补偿和防悬挂必须显式实现
TCC 的 Try/Confirm/Cancel 方法由开发者完全控制,但 Seata-Go 不会自动帮你判断是否需要执行 Cancel——它只按协议调用,不管业务状态。这意味着空补偿(Confirm/Cancel 被重复调用)和悬挂(Try 成功但 Confirm 未触发,后续 Cancel 误删预留资源)必须自己编码防御。
-
Try()返回值必须含唯一业务 ID(如订单号),用于 Confirm/Cancel 参数校验 -
Confirm()和Cancel()开头必须查库确认 Try 是否真正执行过,否则可能重复扣减或释放 - 推荐在
Try()中写入状态表(如tcc_action_log),记录 try_id、status、gmt_create,Confirm/Cancel 均先查此表再操作 - 注册资源时要用
tcc.RegisterTCCResource(),且 struct 必须导出(首字母大写),否则反射失败
XID 跨服务传递:HTTP Header 是默认路径,gRPC 需额外适配
Seata-Go 默认通过 XID header 透传全局事务 ID,但仅限 HTTP 场景。如果你用 gRPC 或消息队列,这个机制就断了——rootContext.GetXID() 在下游服务里会是空字符串。
- HTTP 服务间调用:用
req.Header.Set("XID", rootContext.GetXID())即可,中间件会自动绑定 - gRPC:需在 metadata 中塞入
XID,并在服务端用grpc.UnaryServerInterceptor提取并设置到 context - Kafka/RabbitMQ:XID 必须序列化进消息 body(如 JSON 字段
xid),消费者收到后手动调用rootContext.Bind(xid) - 别依赖
context.WithValue()传递 XID,Seata-Go 的上下文绑定是线程局部的,goroutine 切换后就失效
配置加载与服务发现:vgroup-mapping 错配会导致 TC 找不到 RM
vgroup-mapping 是 Seata-Go 最容易配错的地方。它不是服务名,也不是集群名,而是 tx-service-group 到注册中心分组的映射——如果映射值和 TC 实际注册的分组不一致,RM 就永远注册不上,日志里只显示 “no available server”,没有具体提示。
-
tx-service-group必须和 TC 启动参数-p tx-service-group=my_tx_group完全一致(包括大小写) -
vgroup-mapping.my_tx_group的值必须和 TC 注册到 Nacos/Etcd 的service_name或group字段一致(例如 Nacos 中 TC 注册在SEATA_GROUP,这里就得填"SEATA_GROUP") - 配置文件路径若用
client.InitPath("conf/seatago.yml"),该路径必须是运行时工作目录下的相对路径,不是 GOPATH 或 build 输出目录 - TC 地址写成
127.0.0.1:8091在容器环境会失败,必须用宿主机 IP 或 Kubernetes Service 名
Seata-Go 的难点不在初始化那几行代码,而在事务边界与业务逻辑耦合的方式——AT 模式把复杂度藏在 SQL 解析里,TCC 模式把复杂度推给业务代码。选哪个模式,本质是在运维成本和开发成本之间做取舍。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











