[英]SQL Server How to always rollback the entire transaction
我有一些不寻常的交易处理需求。
我正在为SQL Server设计一个变异测试框架,为此,我需要在一个事务内运行测试,以便数据库始终处于测试完成时开始的状态。
但是,我有一个问题,用户可以在测试过程中进行编码,并且可以调用rollback transaction
,该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
有没有办法确保我最终可以始终回滚到初始状态? 我必须考虑到用户可以调用可能嵌套的并且都可以包含事务处理语句的存储过程/触发器。 使用我所有的解决方案,当用户在测试代码中使用回滚tran时,它们就逃避了事务,并且不会清除所有内容
我想要的是,如果用户调用回滚,则仅回滚其事务的一部分,而我在测试初始化之前启动的事务仍然完好无损。
如果有可能,我想防止强迫我的用户使用事务模板,该事务模板在存在事务时使用保存点。
如果没有用户代码的任何通信/规则,我认为这是不可能的。 尽管您做了什么,但是如果用户的代码运行的COMMIT
与当时的@@TRANCOUNT
一样多,则将COMMIT
事务,您将无能为力。
一种执行此操作的方法是,如果您检查/强制执行用户代码,而不是使用COMMIT
, if @@TRANCOUNT>=2 COMMIT
更改为if @@TRANCOUNT>=2 COMMIT
。 这将确保只能通过YOUR COMMIT
命令完成TRUE数据提交。 当然,您确实不想提交,所以您只需rollback
就可以了。
您提到:
我想要的是,如果用户调用回滚,则仅将其部分事务回滚
请注意,嵌套交易是一种神话。 请参阅这篇出色的文章 。 长话短说:“嵌套” BEGIN TRANSACTION
和COMMIT
实际上除了更改系统变量var @@TRANCOUNT
的值外实际上什么也不做,因此可以通过过程来进行某些组织。
我认为不可能回滚一部分交易并保持另一笔交易不变。 我们回滚事务的那一刻,整个事务都会回滚。
如服务器端所指出的,SQL Server不支持其他嵌套事务。 我决定在用户代码之后尽量减少状态更改语句的数量,并在测试批处理开始时清理这些语句。 通过这种方式,我不能回滚自己的事务并不重要,因为繁重的工作将由我或用户回滚。
当起始@@ TRANCOUNT和结束@@ TRANCOUNT不匹配时,我还决定使测试失败,以便在用户事务出现问题时无法通过任何测试。
但是,当前系统仍将与用户进行COMMIT TRAN斗争。 这又是一个问题。
我认为实际需要是为T-SQL编写测试用例。 如果那是正确的话,那么我觉得您不必重新发明轮子并开始使用开源测试框架T-SQLT https://tsqlt.org/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.