2013-04-16 26 views
5

Từ mã dưới đây, chúng tôi nhận được ngoại lệ tại raiseerror - Giao dịch hiện tại không thể được cam kết và không thể hỗ trợ các hoạt động ghi vào tệp nhật ký. Quay trở lại giao dịch.Giao dịch hiện tại không thể được cam kết và không thể hỗ trợ các thao tác ghi vào tệp nhật ký. Quay trở lại giao dịch

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

Đoạn mã trên có trong giao dịch và/hoặc trong khối TRY..CATCH không? Cài đặt XACT_ABORT tại thời điểm đoạn mã này sẽ được chạy là gì? Ngoài ra, có một kích hoạt trên dbo.CorrectionType? –

+0

mã này được gọi từ một proc khác, đã bắt đầu và giao dịch. XACT_ABORT đã bật. có kích hoạt tồn tại, tuy nhiên tại beginnig chúng tôi đang vô hiệu hóa các kích hoạt và cho phép họ trở lại ở cuối. Đây là mã hoàn chỉnh để bạn tham khảo: –

+1

Nếu bạn đang thực hiện lệnh 'EXISTS()', bạn không nên làm bất cứ điều gì buồn cười với truy vấn như 'TOP 1' hoặc' ORDER BY' - tất cả những gì bạn làm là làm xáo trộn truy vấn và có thể khiến trình tối ưu hóa làm điều gì đó ngu ngốc (chẳng hạn như thực hiện toàn bộ tập kết quả). 'EXISTS()' của chính nó là đủ thông minh để thoát ra khi nó được nhìn thấy một hàng kết quả duy nhất. –

Trả lời

6

Bởi vì bạn có SET XACT_ABORT ON' when you do your RAISERROR() you're setting the XACT_STATE` -1 có nghĩa là bạn không thể làm bất cứ công việc committable hơn đối với cơ sở dữ liệu, bạn chỉ có thể quay trở lại giao dịch của bạn.

Một ví dụ sử dụng procs tạm thời và là một trong trigger của bạn ở trên:

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 

Bạn có một vài lựa chọn, tôi tin rằng:

  1. Set XACT_ABORT để OFF cho proc này. Điều đó sẽ xử lý vấn đề XACT_STATE cho trường hợp cụ thể này và ROLLBACK của bạn sẽ xử lý vấn đề kích hoạt của bạn.
  2. Chuyển các trình kích hoạt ENABLE/DISABLE thành cha mẹ của bạn và xử lý chúng bên ngoài giao dịch hoàn toàn. Họ không cần phải phụ thuộc vào các hành động khác của bạn trong số đứa trẻ này; bạn luôn tắt/bật chúng.
+0

Đặt chức năng bật/tắt kích hoạt bên ngoài giao dịch đã khắc phục sự cố .. –

+0

Rất vui khi bạn có thể giải quyết vấn đề. –

0

Trong trường hợp của tôi điều này được chứng minh là môi trường: dịch vụ Điều phối giao dịch phân phối đã dừng. Khởi động lại dịch vụ Windows này đã khắc phục sự cố cho chúng tôi.

Các vấn đề liên quan