tachibana22 commented on PR #1161:
URL:
https://github.com/apache/incubator-seata-go/pull/1161#issuecomment-5521564281
本次 pr 的核心本质是修复 gRPC 特性合入(PR #1113)时引入的事务上下文隔离回退缺陷(Issue
#1155),解决嵌套事务中内层逻辑篡改外层角色导致二阶段提交被跳过的问题。当前改动严格收敛在事务执行层与单测层,包含 1
行生产代码替换及相应的全量事务传播特性测试矩阵。最终走向为通过 Go Context 树状派生机制恢复事务作用域隔离,并在 CI
流程中建立防回归卡点,确保分布式事务提交的原子性与数据一致性。
**生产代码改动说明:`pkg/tm/transaction_executor.go**`
* **改动位置与内容**:在 `WithGlobalTx` 函数第 57–60 行,将原本调用的原地清除函数 `ClearTxConf(ctx)`
替换为上下文派生调用 `ctx = transferTx(ctx)`,并增加了防止后续重构误删的机制注释。
* **缺陷根因与内存模型机制**:
* Seata-Go 的事务上下文通过 `*ContextVariable` 指针挂载在标准库 Context 中。
* 原代码使用的 `ClearTxConf(ctx)` 会直接对当前 Context 所持有的结构体进行就地(in-place)写入。当嵌套调用
`Required` 事务时,内层事务执行 `UseExistGtx` 会将共享内存中的角色修改为 `Participant`。
* 内层执行完毕退出后,外层事务持有的仍然是被篡改的 `Participant` 角色。外层 defer 中的 `CommitOrRollback`
据此判定当前事务无需负责二阶段,直接跳过 TC 端的提交调用,导致数据未提交。
* **修复原理与生命周期恢复**:
* `transferTx(ctx)` 内部调用 `InitSeataContext(ctx)` 重新分配独立的
`&ContextVariable{}` 结构体,仅拷贝父级 `XID`。
* 内层事务对角色、名称和状态的所有写操作被严格限制在子 Context 内存块中。内层函数栈退出后,外层继续持有的父 Context 依然保有原始的
`Launcher`(发起者)角色与状态,外层正常向 TC 发送二阶段 Commit 请求。
**测试代码改动说明:`pkg/tm/transaction_executor_test.go**`
测试文件位于 `package tm_test`,改动在文件末尾追加了两个独立的测试函数,复用既有的
`globalTransactionManagerStub` 桩对象进行无依赖断言。
* **精准回归测试:`TestNestedRequiredMustCommitOuterTransaction**`
* 场景:`Required -> Required` 嵌套调用。
* 验证事实:通过 Mock 记录提交序列,断言 `committedXids` 集合长度严格为 1 且提交的 XID 为外层生成的
`xid-1`,证实内层退出后外层的 Launcher 提交逻辑已被正确恢复。
* **表驱动传播矩阵测试:`TestGlobalTxPropagationMatrix**`
* 场景覆盖:系统化验证 6 种传播行为在正常、异常及边界条件下的执行流:
* **`Required -> Required`**:覆盖正常执行(提交 `xid-1`)、内层返回错误(回滚 `xid-1`)以及内层触发
panic(捕获后安全回滚 `xid-1`,无悬挂事务)。
* **`Required -> RequiresNew`**:验证独立生命周期与解耦特性。正常路径断言内层提交 `xid-2` 且外层提交
`xid-1`;内层报错时两层分别回滚;新增 `OuterError_InnerCommitted` 用例验证内层成功提交 `xid-2`
后外层发生错误仅回滚 `xid-1`,确认已提交的子事务不受父事务回滚影响。
* **`Required -> NotSupported`**:断言内层执行时 `tm.IsGlobalTx(innerCtx)` 严格为
`false`,内层在无事务状态下运行,外层依然正常提交 `xid-1`。
* **`Required -> Supports` 与 `Required ->
Mandatory**`:验证内层作为参与者静默加入,最终由外层发起者统一提交 `xid-1`。
* **`Required ->
Never`**:验证异常传播硬拦截。当外层已存在事务时,内层直接在开启阶段失败,断言显式确认业务回调未被执行(`wantInnerExecuted:
false`),外层感知错误并安全回滚 `xid-1`。
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]