2013-04-16 71 views
5

從下面的代碼中,我們得到了raiseerror的異常 - 當前事務不能被提交,並且不能支持寫入日誌文件的操作。回滾事務。當前事務不能提交,並且不能支持寫入日誌文件的操作。回滾事務

IF @insertOrUdate = 'D' 
BEGIN 

    -- DescType depends on CorrectionType and is also a protected sync table, 
    -- it needs to be cleared out before we can remove this type 
    IF EXISTS(
     SELECT TOP 1 * 
     FROM [dbo].[DescType] 
     WHERE 
      [CorrectionTypeId] = @correctionTypeId 

    ) 
    BEGIN 
    PRINT 'raise error' 
     RAISERROR('Dependent Desc Role Type Rollups must be removed prior to removing a type that they depend on', 16, 1) 

     PRINT 'after raise error' 
    END 

    -- Delete protected Sync record 
    DELETE FROM [dbo].[CorrectionType] WHERE [CorrectionTypeId] = @correctionTypeId; 

END; 
+0

上面的代碼片斷是在事務中還是在TRY..CATCH塊中?在此代碼段運行時,XACT_ABORT設置是什麼?另外,dbo.CorrectionType是否有觸發器? –

+0

這段代碼是從另一個proc調用的,它有開始和提交事務。 XACT_ABORT已打開。是的觸發器存在,但是在beginnig中,我們禁用了觸發器並在結束時啓用它們。這裏是完整的代碼供你參考: –

+1

如果你正在做一個'EXISTS()'調用,你不應該對查詢做任何有趣的事情,比如'TOP 1'或'ORDER BY' - 你所做的只是混淆該查詢並可能導致優化器做一些愚蠢的事情(比如實現整個結果集)。 EXISTS()本身足夠聰明,只要看到單個結果行就可以退出。 –

回答

6

因爲你有SET XACT_ABORT ON' when you do your RAISERROR()you're setting the XACT_STATE`爲-1,這意味着你不能做任何更多的可提交工作到數據庫中,你只能回滾事務。

使用臨時特效及以上的觸發器的一個例子:

create proC#a 
as 
--This is the proxy for the parent proc 
begin try 
begin tran 
    exeC#b 
commit tran 
end try 
begin catch 
    if @@trancount > 0 rollback 
    select error_message(); 
end catch 

go 

create proC#b 
as 
set xact_abort on; 

begin try; 
    DISABLE TRIGGER [dbo].[trg_dml_CorrectionType_InsteadOfDelete] ON [dbo].[CorrectionType]; 
    --Check state 
    select xact_state() one; 

    raiserror('Error!', 16,1) 

    --This one doesn't run of course 
    select xact_state() two 
end try 
begin catch 
    select xact_state() three; 
    select error_message() as msgprior; 

ENABLE TRIGGER [dbo].[trg_dml_CorrectionType_InsteadOfDelete] ON [dbo].[CorrectionType]; 

    --This doesn't run either, new error 
    select xact_state() four; 

    --if @@trancount > 0 rollback transaction; 
    declare @error nvarchar(2500) 
    select @error = error_message() 
    raiserror(@error, 16,1); 
end catch 

GO 

exeC#a 

您有幾種選擇,我相信:

  1. XACT_ABORT設置爲OFF這個PROC。這應該爲這個特定場景處理 XACT_STATE問題,並且您的ROLLBACK 應該處理您的觸發問題。
  2. 將您的ENABLE/DISABLE觸發器 移至您的父級過程,並完全在交易 之外處理它們。他們不需要依賴於你的其他行動 這個孩子proc;無論如何你總是禁用/啓用它們。
+0

將觸發器禁用/啓用功能置於事務處理之外解決了此問題。 –

+0

很高興您能夠解決問題。 –

0

在我的情況下,這證明是環境問題:分佈式事務處理協調器服務已停止。重新啓動這個Windows服務爲我們解決了這個問題。

相關問題