具有嵌套事务的SQL Try / Catch逻辑

时间:2011-12-10 01:56:22

标签: sql-server sql-server-2008 tsql sqltransaction nested-transactions

以下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

1 个答案:

答案 0 :(得分:5)

不同之处在于您不会引发异常。如果XACT_STATE()在catch块中为-1(即不可提交的事务,就像死锁一样)在这种情况下你的程序会回滚(必须,它在-1情况下没有选择)但是返回w / o提出例外。因此,不匹配。您必须引发异常并在调用者中捕获它。

请参阅Uncommittable Transactions and XACT_STATE

  

如果TRY块中产生的错误导致当前状态   交易无效,交易被归类为   不可承认的交易。通常结束交易的错误   在TRY区块之外导致交易无法进入   在TRY块内发生错误时的状态。一个不容置疑的   事务只能执行读操作或ROLLBACK   交易。该事务无法执行任何Transact-SQL   将生成写操作或COMMIT的语句   交易。如果是,XACT_STATE函数返回值-1   交易已被归类为不可提交的交易。

死锁总是会导致无法进行的交易。实际上,在死锁的情况下,当你捕获死锁异常时,事务已经作为死锁牺牲品回滚。

相关问题