1. 问题描述
在使用 activerecord-sqlserver-adapter 时,事务块内抛出 ActiveRecord::Rollback 异常或直接触发异常后,事务未正确回滚,而是被提交(日志显示 COMMIT TRANSACTION)。此行为与预期不符,导致数据一致性问题。
2. 重现步骤
- 使用以下代码逻辑执行事务:
ActiveRecord::Base.transaction do Contract.create!(result) # 假设 result 是有效数据 AnotherModel.create!(another_result) # 假设 another_result 是有效数据 raise ActiveRecord::Rollback # 或 raise "Test error" end - 观察日志输出:
TRANSACTION (2.3ms) COMMIT TRANSACTION => nil - 检查数据库表中的数据是否已被提交(而非回滚)。
3. 预期行为
- 当事务块内抛出
ActiveRecord::Rollback或非ActiveRecord::Rollback异常时,事务应被回滚(日志显示ROLLBACK TRANSACTION),且数据库中的数据应无变化。
4. 实际行为
- 事务被提交(日志显示
COMMIT TRANSACTION),数据被持久化到数据库,未回滚。
5. 环境信息
| 项目 | 详细信息 |
|---|---|
| activerecord-sqlserver-adapter version | 7.0.7 |
| Rails version | 7.0.8.6 |
| Ruby version | 3.3.3 |
| SQL Server version | 2014 |
| Database Configuration | |
| 数据库连接配置 |
production:
sqlserver:
adapter: sqlserver
database: my_databse
username: user
password: psword!
host: 192.168.28.102
port: 1433
timeout: 5000
options: "XACT_ABORT=true" # Setting or not setting it here has no effect
6. 日志输出
请提供完整的日志片段(脱敏敏感信息):
[事务开始前的日志]
TRANSACTION (1.7ms) BEGIN TRANSACTION
[数据库操作日志]
TRANSACTION (2.3ms) COMMIT TRANSACTION
7. 已尝试的解决方案
- ✅ 使用
ActiveRecord::Base.transaction替代手动调用begin_transaction。 - ✅ 在事务块内抛出
ActiveRecord::Rollback。 - ✅ 在
database.yml中添加options: "XACT_ABORT=true"。 - ✅ 升级
activerecord-sqlserver-adapter到最新版本(运行bundle update activerecord-sqlserver-adapter)。
8. 附加信息
- 是否涉及嵌套事务?
(例如:是否在事务块内调用了其他事务方法?) - 是否使用了自定义的
after_commit/after_rollback回调?
(这些回调可能隐式提交事务。) - 是否在事务块外捕获了异常?
(例如:rescue吞掉了异常,导致未重新抛出。)
请求帮助
请社区协助确认以下问题:
- 是否是
activerecord-sqlserver-adapter的已知问题? - 是否与 SQL Server 的
XACT_ABORT配置相关? - 是否需要进一步调试底层事务管理逻辑?