6.5 KiB
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:六种结果通过,包括“已保存但提交报错”时不清理文件的演示决策;示例没有真实文件删除。- checked-in managedService 的生成检查、race 和根目录 build 通过。
| 场景 | 验证结果 |
|---|---|
| 开启失败 | 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 不属于本次接口。
远程版本验收
v0.25.0-preview 标签固定在 7a177744ab2bb85f23efc0ec267fd905d349bd4b,checksum 为 h1:R1rDYtPBWRfRNHY2Px1gZF3/xpit6Pttd7AvIbMJpKs=。
- 空 module 缓存安装 CLI,固定远程依赖、无本地 replace,77 项检查通过,耗时 71.93 秒。9 组生成消费者、下载模块 database/config/httpc/copyx/logx/cors/app 的 race、事务示例、生成检查与业务文件保留通过。见 transactionRemote.json。
- 独立空缓存下载同一版本,53 条 MySQL 测试记录(含子用例)通过,耗时 28.49 秒。真实 TLS 数据库提交/回滚后的确认丢失、GORM、生成项目与后台 drain 验收通过;独立容器和临时资源已清理。见 transactionMySQLRemote.json。
python3 scripts/verifyManagedRelease.py --version v0.25.0-preview --report reports/transactionRemote.json
python3 scripts/verifyConnector.py --version v0.25.0-preview --gorm --phases --report reports/transactionMySQLRemote.json
发布标签不随验收记录提交移动。