25

有时我会看到以下代码片段。什么时候if @@trancount > 0需要begin try?两个都?或者它是一种安全的方式(最佳实践)来检查它,以防它在检查之前回滚?

begin tran
begin try
  ... just several lines of sql ...
  if @@trancount > 0 commit tran
end try
begin catch
  if @@trancount > 0 rollback tran
end catch
4

4 回答 4

8

我可以想到一些在处理时要考虑的场景@@trancount

  1. 当前事务是从另一个具有自己事务的存储过程中调用的
  2. 当前事务由一些具有自己事务的 .NET 代码调用
  3. 当前交易是唯一的交易

我相信 Remus Rusanu 的异常处理和嵌套事务处理了所有这些可能性。

于 2012-12-21T04:33:17.117 回答
2

当你不使用@@trancount时,嵌套事务存储过程的错误信息不会返回错误的确切原因只是reurtn“回滚事务请求没有相应的开始事务”,否则它给出了错误的确切原因,所以它使用正确的语法很容易处理错误。

于 2018-10-11T04:33:05.603 回答
2

回答这个问题 - 执行@@trancount 的时间是中间的代码是否可能已经执行了您启动的事务的提交或回滚。因此,例如,如果您正在调用存储过程 - 然后在最后执行检查。

顺便说一句,而不是做一个 if @@trancount>0 我建议最好在代码块的开头检查 @@trancount ,然后看看计数是否在最后增加了,在这种情况下做提交或回滚,取决于 try/catch。

特别是如果您处于触发器中,因为 @@trancount 将始终为 1,因此仅执行 @@trancount>0 可能会导致错误。

但是,即使您的代码只是在存储过程中,假设它被另一个本身具有打开事务的过程调用,如果您的代码错误并回滚,那么外部存储过程也将回滚其事务(参见https: //www.sqlskills.com/blogs/paul/a-sql-server-dba-myth-a-day-2630-nested-transactions-are-real/)。

所以

开始 TRAN 打印@@TRANCOUNT

开始 TRAN 打印@@TRANCOUNT

回滚 TRAN 打印 @@TRANCOUNT

显示 1 2 0

So basically - if the code in the middle is calling other procedures, you need to perform the IF @@TRANCOUNT check.

于 2019-05-10T11:59:05.773 回答
0

检查的原因是,如果您在@@trancount=0 时提交trans 或回滚它,您会收到带有此错误消息的异常:COMMIT TRANSACTION 请求没有相应的BEGIN TRANSACTION。

于 2018-12-18T21:25:11.743 回答