我对交易处理有一些不同寻常的需求。
我正在为 SQL Server 开发一个突变测试框架,为此我需要在一个事务中运行我的测试,以便数据库在测试完成时始终处于它开始时的状态。
但是我有一个问题,用户可以在测试过程中编写代码,并且可以调用可能在也可能不在(嵌套)事务(保存点)内的rollback transaction
。
高层看起来像这样
start transaction
initialize test
run test with user code
may or may not contain:
- start tran
- start tran savename
- commit tran
- commit tran savename
- rollback tran
- rollback tran savename
output testresults
rollback transaction
有没有办法确保我最终总能回滚到初始状态?我必须考虑到用户可以调用可能嵌套并且都可以包含事务语句的存储过程/触发器。使用我所有的解决方案,当用户在他们的测试代码中使用 rollback tran 时,他们会逃避交易,并不是所有的东西都会被清理
我想要的是,如果用户调用回滚,只有他们的事务部分被回滚,而我在测试初始化之前开始的事务仍然完好无损。
如果可能的话,我想防止在事务已存在时强制我的用户使用使用保存点的事务模板。
最佳答案
如果没有针对用户代码的任何通信/规则,我认为这是不可能的。不管你做什么,如果用户的代码运行了与当时 @@TRANCOUNT
一样多的 COMMIT
,事务将被提交,你将无能为力做那个。
你可以这样做的一种方法是,如果你检查/强制用户代码,而不是使用 COMMIT
,将其更改为 if @@TRANCOUNT>=2 COMMIT
.这将确保 TRUE 数据提交只能通过您的 COMMIT
命令完成。当然,有时您真的不想提交,所以您只需rollback
就可以结束。
你提到:
What I want is that if a user calls rollback only their part of the transaction is rolled back
请注意嵌套事务是一种神话。引用this excellent article .长话短说:“嵌套”BEGIN TRANSACTION
和 COMMIT
实际上除了更改系统变量 @@TRANCOUNT
的值外什么都不做一些组织可以通过程序进行。
关于SQL Server 如何始终回滚整个事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56804224/