以下sproc是根据本文中的模板实现的:Exception handling and nested transactions。这个sproc应该处理死锁,它由已经创建事务的另一个sproc调用。内部事务的BEGIN / COMMIT的一些魔法是不匹配的,因为我得到了这个例外:Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0
。据我所知,catch被执行,@xstate = -1
为真,整个外部事务被回滚。
发生不匹配的任何想法?
CREATE PROCEDURE [dbo].[mysproc]
AS
BEGIN
SET NOCOUNT ON;
SET DEADLOCK_PRIORITY LOW;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRY
DECLARE @trancount int;
SET @trancount = @@TRANCOUNT;
IF (@trancount = 0)
BEGIN TRANSACTION;
ELSE
SAVE TRANSACTION InnerTran;
--
-- do some work that can potentially cause a deadlock
--
END TRY
BEGIN CATCH
DECLARE @xstate int
SELECT @xstate = XACT_STATE()
IF (@xstate = - 1)
ROLLBACK;
IF (@xstate = 1 and @trancount = 0)
ROLLBACK;
IF (@xstate = 1 and @trancount > 0)
ROLLBACK TRANSACTION InnerTran;
END CATCH
END
GO
答案 0 :(得分:5)
不同之处在于您不会引发异常。如果XACT_STATE()
在catch块中为-1(即不可提交的事务,就像死锁一样)在这种情况下你的程序会回滚(必须,它在-1情况下没有选择)但是返回w / o提出例外。因此,不匹配。您必须引发异常并在调用者中捕获它。
请参阅Uncommittable Transactions and XACT_STATE:
如果TRY块中产生的错误导致当前状态 交易无效,交易被归类为 不可承认的交易。通常结束交易的错误 在TRY区块之外导致交易无法进入 在TRY块内发生错误时的状态。一个不容置疑的 事务只能执行读操作或ROLLBACK 交易。该事务无法执行任何Transact-SQL 将生成写操作或COMMIT的语句 交易。如果是,XACT_STATE函数返回值-1 交易已被归类为不可提交的交易。
死锁总是会导致无法进行的交易。实际上,在死锁的情况下,当你捕获死锁异常时,事务已经作为死锁牺牲品回滚。