【问题标题】:The Rollback transaction request has no corresponding begin transaction回滚事务请求没有对应的开始事务
【发布时间】:2016-08-02 10:32:17
【问题描述】:

我使用了保存事务和回滚,但仍然出现同样的异常。

它给了我这个错误:

消息 3903,级别 16,状态 1,过程 HALAQATI_ttttttttttttt,行 144 ROLLBACK TRANSACTION请求没有对应的BEGIN 交易。

更新

消息 50000,级别 16,状态 1,过程 HALAQATI_ttttttttttttt,行 160 usp_my_procedure_name: 102: '=' 附近的语法不正确。

存储过程是:

ALTER Proc [dbo].[HALAQATI_ttttttttttttt]
                @tf_commentparam nvarchar(100),
                @tf_secsuggdate int,
                @tf_testplace nvarchar(50),
                @tf_time nvarchar(7),
                @tf_day int,
                @an_id int,
                @ResponseText nvarchar(max) out,
                @ResponseNum int out -- (0 = everything is ok , 1 = error or wrong data)

AS
    DECLARE @startingTranCount int
    SET @startingTranCount = @@TRANCOUNT
Begin
SET XACT_ABORT ON
SET NoCount ON
    BEGIN TRY
    IF @startingTranCount > 0
        SAVE TRANSACTION mySavePointName
    ELSE
        BEGIN TRANSACTION

            DECLARE @return_value_FIRST int,
                @tf_id int,
                @createddate int,
                @UnitIDFromStudentID int,
                @StudentIDFromAutoNominationID int

            set @createddate  = (select dbo.f_getHijNowByInteger());

            set @StudentIDFromAutoNominationID = (select st_id from tbl_autonomination where an_id = @an_id);

            set @UnitIDFromStudentID =  (select sec_id from tbl_secmsq where sm_id = 
                                        (select sm_id from tbl_ring where rg_id = 
                                        (select Ring_ID from HALAQATI_VIEW_GetAllStudents where Student_ID = @StudentIDFromAutoNominationID)))
                                        --/////////////////////////////////--
            DECLARE @return_value_SECOND int,@msg nvarchar(500)

            Declare @BranchNumFromAnID int = (select ne_branchno from tbl_nomineeexam where an_id = @an_id)
                                        --/////////////////////////////////--
            DECLARE @return_value_THIRD int
                                        --/////////////////////////////////--

    EXEC        @return_value_FIRST = [dbo].[sp_inserttestform]
                @tf_comment = @tf_commentparam,
                @tf_date = @createddate,
                @tf_secsuggdate = @tf_secsuggdate,
                @tf_testplace = @tf_testplace,
                @tf_unittype = 1, -- قطاع
                @tf_unitid = @UnitIDFromStudentID,
                @tf_id = @tf_id OUTPUT,
                @tf_userid = 10,--رقم جلال سعيد في التعليمية,
                @tf_type = 1, --آلي
                @tf_time = @tf_time,
                @tf_day = @tf_day,
                @tf_TFtype = 1 -- أجزاء

                if (@return_value_FIRST != 0 and @tf_id is null)
                begin

                    if (@return_value_FIRST = 1)        
                        begin
                            set @ResponseText  =  'أقل من يوم وأكثر من 15 يوم' 
                            set @ResponseNum = 1
                            return
                        end
                    else if (@return_value_FIRST = 2)
                        begin
                            set @ResponseText = 'لايوجد نقاط كافية للترشيح'
                            set @ResponseNum = 1
                            return
                        end
                    else if (@return_value_FIRST = 3)
                        begin
                            set @ResponseText = 'لم يتم ربط مركز الإشراف أو المجمع بمشرف لجان'
                            set @ResponseNum = 1
                            return
                        end
                    else
                        begin
                            set @ResponseText =  'هناك خطأ حاول في وقت لاحق' 
                            set @ResponseNum = 1
                            return
                        end
                                IF @startingTranCount > 0
                            ROLLBACK TRANSACTION MySavePointName
                        ELSE
                            ROLLBACK
                End

    EXEC        @return_value_SECOND = [dbo].[sp_insertAutoNominee]
                @tf_id = @tf_id,
                @st_id = @StudentIDFromAutoNominationID,
                @an_id = @an_id,
                @ne_branchno = @BranchNumFromAnID,
                @ne_userid = 10,
                @msg = @msg OUTPUT

                if (@return_value_SECOND != 0 or @return_value_SECOND is not null)
                    begin
                         --ROLLBACK TRANSACTION

                         if CHARINDEX('بنفس الفرع ونتيجته ناجح',@msg) > 0
                            begin
                                set @ResponseText  = 'لا يمكن إضافة ترشيح للطالب لأن له ترشيح سابق بنفس الفرع ونتيجته ناجح أو لم يختبر بعد'
                                set @ResponseNum = 1
                                return
                            end              
                         if CHARINDEX('خلال السبعة أيام',@msg) > 0
                            begin
                                set @ResponseText  = 'لا يمكن إضافة ترشيح للطالب لأنه غاب عن اختبار في نفس الفرع خلال السبعة أيام الماضية'
                                set @ResponseNum = 1
                                return
                            end                      
                         if CHARINDEX('خلال الأربعة عشر يوماً',@msg) > 0
                            begin
                                set @ResponseText  = 'لا يمكن إضافة ترشيح للطالب لأنه رسب في نفس الاختبار خلال الأربعة عشر يوماً الماضية'
                                set @ResponseNum = 1
                                return
                            end             
                                IF @startingTranCount > 0
                            ROLLBACK TRANSACTION MySavePointName
                        ELSE
                            ROLLBACK                    
                    end

    EXEC        @return_value_THIRD = [dbo].[sp_changeTFState]
                @tf_state = 4,
                @tf_id = @tf_id,
                @tf_chatsys = NULL,
                @tf_testdate = @tf_secsuggdate,
                @tf_time = @tf_time,
                @tf_day = @tf_day,
                @ne_cerprintdate = NULL

                IF @startingTranCount = 0

                    set @ResponseText = 'تم إعتماد و ترشيح الطالب إلى الإختبار بنجاح , وتم إرسال كافة البيانات إلى قسم الإختبارات في الجمعية'
                    set @ResponseNum  = 0
                    COMMIT
    END TRY
    --BEGIN CATCH
    --IF @startingTranCount > 0
    --  ROLLBACK TRANSACTION MySavePointName
    --ELSE
    --  ROLLBACK TRANSACTION
    --  set @ResponseText = ERROR_MESSAGE ()   
    --  set @ResponseNum = 1
    --END CATCH  
       begin catch
        declare @error int, @message varchar(4000), @xstate int;
        select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
        if @xstate = -1
            rollback
        if @xstate = 1 and @startingTranCount = 0
            rollback
        if @xstate = 1 and @startingTranCount > 0
            rollback transaction usp_my_procedure_name;

        raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
    end catch   
End

【问题讨论】:

  • 你有一个 BEGIN TRANSACTION 然后是一个 ROLLBACK TRANSACTION ,然后是第二个没有 BEGIN 的 ROLLBACK TRANSACTION - 我先看看那里
  • @AndrewDeighton 好的,但是当我需要在 sp 块的两个位置使用多个回滚时怎么办?
  • 在第一次 ROLLBACK 之后,您真的要继续进行第二次操作吗?如果不这样做,则需要设置一个标志以避免第二次操作。
  • @AndrewDeighton 但我与 Return 分手了
  • 如果你到达 IF @startingTranCount > 0 行,那么你回滚并继续,我想

标签: sql-server tsql sql-server-2014


【解决方案1】:

如果没有先咨询XACT_STATE() 的状态,您将无法回滚CATCH 块。您的 catch 块可能会在事务回滚后执行(想想,例如,捕获死锁)。

请参阅Exception handling and nested transactions 了解正确的模式:

create procedure [usp_my_procedure_name]
as
begin
    set nocount on;
    declare @trancount int;
    set @trancount = @@trancount;
    begin try
        if @trancount = 0
            begin transaction
        else
            save transaction usp_my_procedure_name;

        -- Do the actual work here

lbexit:
        if @trancount = 0   
            commit;
    end try
    begin catch
        declare @error int, @message varchar(4000), @xstate int;
        select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
        if @xstate = -1
            rollback;
        if @xstate = 1 and @trancount = 0
            rollback
        if @xstate = 1 and @trancount > 0
            rollback transaction usp_my_procedure_name;

        raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
    end catch   
end

【讨论】:

  • 感谢 Xact_state 信息 .. 一个问题 .. 在到达 catch 语句之前死锁会自动回滚吗?
  • 当遇到死锁时,受害事务被中止并回滚,只有回滚完成后才会在受害会话中引发死锁异常。
  • @RemusRusanu 谢谢,我不知道为什么问题仍然存在,我已经用你的方法改变了我的 Whole Catch 但又出现了另一个问题,我已经更新了线程错误
  • 问题是,在这个存储过程中,我调用了 3 个存储过程,每个都有它的事务,这是造成这个问题的原因吗?
  • 你不能简单地回滚和返回,调用者应该如何知道它是否仍然可以提交或必须回滚或已经回滚?仔细想想你是如何混合异常、返回和事务语义的,这远非一个小问题。我的示例是一个模式,如果 every 过程都遵循它。
猜你喜欢
  • 2016-07-26
  • 1970-01-01
  • 2020-04-28
  • 1970-01-01
  • 2015-05-02
  • 2018-06-17
  • 2020-09-10
  • 1970-01-01
  • 2017-02-14
相关资源
最近更新 更多