簡體   English   中英

SQL Server回滾事務來自外部事務錯誤

[英]SQL Server Rollback Transaction From Error Outside Transaction

我有一個TRY CATCH語句,其中TRY中事務中有一些代碼,而TRY中事務中有其他代碼。 如果轉換之外的代碼(仍在TRY中)拋出錯誤,則我的事務不會在CATCH中回滾。 但是,如果我刪除了事務外的代碼,則如果出現錯誤,事務將被回滾。 為什么這樣表現呢? SQL Server 2014。

我的代碼。 如果Remote proc引發錯誤,則事務不會回滾:

BEGIN  try
begin transaction

  INSERT INTO bos_south_florida_job_map (job_id, original_job_id, 
created_date, updated_date,completed_status_sent_ind, 
assigned_status_sent_ind, status_prev)
VALUES (9999, '1234', getdate(), getdate(),0,0,'CREATED');


COMMIT TRANSACTION

declare @sql varchar(max)

set @sql = ''

select @sql = '
   declare @error1 varchar(255),
   @error2 varchar(255),
   @error3 varchar(255)

   Exec NEXTGEN.DBO.wbAf_ConfirmDispatchedReservation ''AFFWEB'', ''A10596'', ''Admin'', ''Admin'', '''+cast(preassignedsubconcode as varchar(100))+''', '''+cast('1234' as varchar(20))+''', '''+convert(char(23),ISNULL(ScheduledDispatchDateTime,''),121)+''', '+cast('1234' as varchar(12))+',null,@error1 output,@error2 output,@error3 output

   if @error1 is not null or @error2 is not null or @error3 is not null
   begin
        set @error1 = @error2 + '' '' + @error3 + '' '' + @error1
        RAISERROR (@error1, 16, 1)
   end
   '
from [BCCUATWSQL290].NEXTGEN.DBO.tbRideResCurDispatch
where resno = '35002616'

   exec(@sql) at [BCCUATWSQL290]

END TRY

BEGIN CATCH

IF @@TRANCOUNT > 0  
ROLLBACK TRANSACTION

DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;

SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE()

INSERT INTO bos_south_florida_error_log (original_job_id, [action], 
error_datetime, [error_message])
SELECT
    '1234',
    'CREATE_JOB',
    GETDATE(),
    'Msg: ' + ISNULL(CONVERT(VARCHAR, ERROR_NUMBER()), 'N/A') + ', Level: ' + ISNULL(CONVERT(VARCHAR, @ErrorSeverity), 'N/A') + ', Line: ' + ISNULL(CONVERT(VARCHAR, ERROR_LINE()), 'N/A') + ', Error: ' + ISNULL(@ErrorMessage, 'N/A')


END CATCH

這將回滾事務:

BEGIN  try
begin transaction

  INSERT INTO bos_south_florida_job_map (job_id, original_job_id, 
created_date, updated_date,completed_status_sent_ind, 
assigned_status_sent_ind, status_prev)
VALUES (9999, '1234', getdate(), getdate(),0,0,'CREATED');

RAISERROR ('BLAH', 16, 1)

COMMIT TRANSACTION

END TRY

BEGIN CATCH

IF @@TRANCOUNT > 0  
ROLLBACK TRANSACTION

DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;

SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE()

INSERT INTO bos_south_florida_error_log (original_job_id, [action], 
error_datetime, [error_message])
SELECT
    '1234',
    'CREATE_JOB',
    GETDATE(),
    'Msg: ' + ISNULL(CONVERT(VARCHAR, ERROR_NUMBER()), 'N/A') + ', Level: ' + ISNULL(CONVERT(VARCHAR, @ErrorSeverity), 'N/A') + ', Line: ' + ISNULL(CONVERT(VARCHAR, ERROR_LINE()), 'N/A') + ', Error: ' + ISNULL(@ErrorMessage, 'N/A')


END CATCH

回想一下,每個Begin Transaction@@Trancount增加1,而每個Commit將其減少1。

在第一個示例中,事務已經提交,並且在引發錯誤之前@@TranCount減小為零,因此在Catch子句中, @@Trancount將為零。 很好 提交的事務已經是歷史記錄,無法回滾。

在第二個示例中,當您在Begin之后但在Commit之前引發錯誤時,到達Catch子句並回滾時, @@TranCount為1。

大概您想要的行為是遠程調用中的錯誤應導致回滾? 您可以通過在遠程調用之后將Commit移至該位置,使其成為End Try之前的最后一條語句來實現。

但是請注意,跨服務器事務比較昂貴,並且要求MS DTC在兩個服​​務器上都運行。 在負載很重的服務器上,DBA可能不願這樣做。

順便說一句,圍繞單個插入的事務通常是沒有意義的。 正常行為是“自動提交”模式,這意味着插入/更新/刪除語句“被看不見的BEGIN TRANSACTION和看不見的COMMIT TRANSACTION語句限制”

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM