seata-golang 不是开箱即用的注解框架,需显式调用事务api或构造代理对象;at模式必须通过datasource.newdbproxy包装*sql.db实例,所有sql操作须经该代理,否则undo日志不生成、回滚失效。

Seata-golang 不是“开箱即用”的注解框架,Go 没有运行时反射增强能力,@GlobalTransactional 这类注解在 Go 里不生效——你必须显式调用事务 API 或构造代理对象,否则事务根本不会注册到 TC。
AT 模式下必须代理 database/sql 的 *sql.DB 实例
Seata-golang 的 AT 模式不是靠 driver 层拦截实现的,而是通过包装 *sql.DB 构造代理对象(如 datasource.NewDBProxy),所有业务 SQL 必须走这个代理实例,否则 undo 日志不会生成,回滚将失效。
- 错误做法:
db := sql.Open("mysql", dsn)直接使用原生*sql.DB - 正确做法:用
datasource.NewDBProxy(db, config)包一层,并确保后续所有db.Query、db.Exec都调用的是该代理对象 - ORM(如 GORM)集成需额外适配:GORM v2 的
Config.DriverName和Config.Dialector无法直接传入代理*sql.DB,需用gorm.Open(gormlogger.New(...), &gorm.Config{...})+ 自定义sql.ConnPool替换底层连接池
TCC 模式要求业务方法严格实现 Try/Confirm/Cancel 三接口
Seata-golang 的 TCC 不支持自动发现或泛化调用,每个资源必须手动注册为 tcc.TCCResource,且三个阶段方法签名必须完全匹配框架约定,否则 TC 无法识别分支事务。
-
Try方法必须返回error,且不能带 context 参数(框架内部注入) -
Confirm和Cancel方法名必须以Try方法名 +"Confirm"/"Cancel"后缀构成,例如TryDeductStock→TryDeductStockConfirm - 所有三方法必须定义在同一个 struct 上,并实现
tcc.Resource接口;若用指针接收者,注册时也必须传指针 - 未配置
tcc.fence-config.enable-persistence: true时,Confirm/Cancel 失败不会重试,直接进入悬挂状态
全局事务 ID(XID)跨服务传递必须手动注入 HTTP Header
Seata-golang 不像 Java 版能自动织入 Web 拦截器,HTTP 调用链中 XID 传递完全依赖开发者在每次 outbound 请求中显式设置 XID header,漏一次就断链,TC 将无法关联分支事务。
- 发起方需调用
rootContext.GetXID()获取当前 XID - 下游请求必须写入:
req.Header.Set("XID", xid),且 header 名大小写敏感(必须是XID,不是xid或Xid) - 下游服务收到后,需立即调用
rootContext.Bind(xid)绑定上下文,否则后续tm.Begin会创建新全局事务 - gRPC 场景需改用 metadata 传递,key 固定为
"xid"(小写),框架内部做了标准化转换
最容易被忽略的是:TC 地址配置中的 vgroup-mapping 必须与代码中 tm.InitGlobalTransaction 传入的 txServiceGroup 完全一致,包括大小写和下划线——错一个字符,RM 就注册失败,日志里只报 “no available server”,不提示具体哪项不匹配。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











