Files
go-omni/reports/transactionAcceptance.md

5.3 KiB
Raw Blame History

v0.25 事务错误验收(2026-09-26)

目标是让业务可靠地区分错误阶段和框架实际掌握的事务结果。保持 InTx 签名,保留原始/回滚错误链;不引入业务补偿、文件删除或事务重试。

回归

  • GO_OMNI_SCAFFOLD_INTEGRATION=1 go test -race ./...:49 个有测试的包通过,包含既有生成消费者、响应目录、生命周期、上传下载、配置等回归。
  • GOTOOLCHAIN=go1.22.12 go test ./database ./errors ./app:通过。
  • go vet ./...、go build ./...:通过。
  • go test -race ./database -run '^TestInTxCancellation' -count=20:通过,包含 20 × 128 次取消与回滚竞争检查。
  • go run ./examples/transactions:六种结果通过,包括“已保存但提交报错”时不清理文件的演示决策;示例没有真实文件删除。
场景 验证结果
开启失败 callback 不执行,StageBegin/NotStarted,原始驱动或 context 原因可 Is/As;nil DB、nil callback 在开启前报错
成功事务 callback/Commit 各一次,返回 nil,不再调用显式 Rollback;context、隔离级别、只读选项传递保持
回调失败 显式回滚 nil 才返回 Work/RolledBack;原始业务原因可 Is/As;回滚报错为 Unknown 且两条原因完整保留
提交失败 同样的驱动错误分别模拟已保存/未保存,都返回 Commit/Unknown;超时、ErrBadConn 也不当成回滚;不重试 Commit/callback
取消 开启前取消、回调取消、自动回滚完成、取消与显式回滚竞争、提交过程中取消;ErrTxDone 从不表示回滚成功
原因链 外层再次 %w 包装后 As/Is 可用;主要 typed cause 优先,回滚 typed cause 可单独找到;嵌套 TxError 不压平
异常与隔离 panic 原值传播,Goexit 正常展开;都尝试一次回滚,不提交;64 个并发调用的原因/结果互不串扰
HTTP 兼容 回调返回业务错误目录引用与参数,包装后仍输出项目 HTTP 200、数字业务码、提示与 data:null;回滚附加原因、提交内部原因不外泄

真实 MySQL

python3 scripts/verifyConnector.py --local --gorm --phases --report reports/transactionMySQL.json

使用独立本地 MySQL 8.4 容器,1 CPU / 768 MiB / 128 pids,TLS 与临时随机凭据;不连接接入项目数据库或远程服务器。53 条通过记录(含子用例),耗时 13.2 秒。容器、数据卷、证书与临时消费者已经清理。完整证据见 transactionMySQL.json。

  • 正常 Commit 后,另一个连接看到记录;回调失败且真实 Rollback 成功,返回 Work/RolledBack,另一个连接确认没有该记录。
  • 在真实驱动 Commit 成功返回后,由测试包装器注入“确认丢失”错误:另一个连接确认记录已经持久化,InTx 返回 Commit/Unknown,没有重试或误报回滚。
  • 在真实驱动 Rollback 成功后注入确认错误:库只能返回 Work/Unknown,并保留业务原因与回滚确认错误;不能利用测试已知的数据库状态推断生产结果。
  • 这是驱动返回边界的确定性故障注入,不等同于覆盖所有 TCP 断线时序。
  • 真实生成项目的配置/TLS/独立连接池/关闭、可选 GORM 事务与连接池归属、后台 drain 后关闭数据库均通过。
  • 本轮发现旧 MySQL 验收脚本仍依赖已移除的自动环境覆盖。现已改为测试配置文件显式引用变量,复测通过;没有恢复旧加载模式。

性能

Go 1.27.1、darwin/arm64、Apple M2 Max。使用相同演示驱动和 benchmark,比较 v0.24 的原 InTx 实现与当前实现,每场景三轮、300ms,取中位数。旧实现从提交 8eddef9cc8e9902150f4f712a40bc761d4350415 取出,临时 benchmark 文件测后删除。原始结果。

场景 原实现 ns/次 当前 ns/次 原分配 当前分配
成功提交 617.3 587.0 392 B / 7 392 B / 7
开启失败 212.9 146.0 96 B / 3 80 B / 2
回调失败并成功回滚 556.5 540.9 280 B / 6 344 B / 7
回调和回滚同时失败 681.1 732.6 416 B / 10 344 B / 7
提交结果不确定 719.6 814.8 472 B / 9 456 B / 8

成功路径没有新增分配。原先直接返回的回调错误现在需要 TxError,增加 64 B / 1 次分配;其他失败路径移除了即时格式化/Join 的部分开销。部分失败路径耗时增加,以上是受 goroutine 调度影响的本机微基准,不含真实数据库网络、SQL 和磁盘耗时,不承诺固定提速比例或服务 QPS。

当前实现复现:

go test ./database -run '^$' -bench '^BenchmarkInTx$' -benchmem -benchtime=300ms -count=3

保证范围

Outcome 只属于当前受管理事务;回调不得自己提交/回滚、执行隐式提交 SQL、把事务交给其他 goroutine。其他连接、独立事务、非事务表、文件和第三方系统的副作用由业务负责。

标准库异步回滚不公开的驱动原因无法还原。只拿到 ErrTxDone 时保守返回 Unknown;直接观察到的回滚失败全部保留。panic/Goexit 保持原有传播,没有普通返回值可携带回滚原因。返回错误的文本/具体最外层类型有变化,调用方使用 errors.Is/As;GORM 自己的 Transaction 不属于本次接口。