【问题标题】:SQL Server mismatching number of BEGIN and COMMIT statements nested transactionSQL Server 嵌套事务的 BEGIN 和 COMMIT 语句数不匹配
【发布时间】:2017-10-11 09:28:41
【问题描述】:

我按照推荐的模板来处理事务中的错误,该模板在现有事务中执行时应该可以工作。

这是我的模板

CREATE PROCEDURE DoSomething
AS
BEGIN
SET NOCOUNT ON
DECLARE @trans INTEGER = @@TRANCOUNT

IF (@trans > 0)
    SAVE TRANSACTION SavePoint
ELSE
    BEGIN TRANSACTION

BEGIN TRY
    -- code with a check that does a THROW if the requirements aren't met
    IF (@trans = 0)
        COMMIT TRANSACTION
END TRY

BEGIN CATCH
    IF (@trans > 0)
        ROLLBACK TRANSACTION SavePoint
    ELSE
        ROLLBACK TRANSACTION

    ;THROW
END CATCH
END

如果我将 TRY 块中的 THROW 替换为 RAISERROR,问题仍然存在。

测试结果:

事务中的执行失败场景:正确的结果(给出正确的错误消息)

事务中的 EXEC 成功场景: 出现意外错误。

EXECUTE 之后的事务计数表明 BEGIN 和 COMMIT 语句的数量不匹配。先前计数 = 1,当前计数 = 2。

事务外的执行失败场景:给出预期错误。

事务外的 EXEC 成功场景: 出现意外错误。错误和上面一样,但是每次执行它都会增加-1。这是否意味着每次都会有更多的东西未被提交?

这是一个测试的样子:

BEGIN TRANSACTION
  EXEC ...
ROLLBACK TRANSACTION

有人知道怎么回事吗?

【问题讨论】:

  • IMPLICIT_TRANSACTIONS 是否开启?
  • 无论默认的 IMPLICIT_TRANSACTIONS 是什么,我都没碰过。
  • 返回什么 SELECT @@OPTIONS & 2
  • 0,所以它似乎关闭了。
  • 请注意嵌套事务是一个谎言。 SQL Server 将计算BEGIN TRANSACTIONCOMMIT,当然,但只有一个事务在进行。保存点并没有真正改变这一点。它们只是让您能够部分回滚。将它与arcane rules that exist for when a transaction is doomed or not(也取决于XACT_ABORT)结合起来,你的手上真的是一团糟。

标签: sql-server transactions nested-transactions


【解决方案1】:

取消注释变量

CREATE PROCEDURE DoSomething
AS
BEGIN
SET NOCOUNT ON
DECLARE @trans INTEGER = @@TRANCOUNT

IF (@trans > 0)
    SAVE TRANSACTION SavePoint
ELSE
    BEGIN TRANSACTION

BEGIN TRY
    DECLARE @f float;
    SET @f = 0;
    --var 1.
    --print  1/0
    --var 2.
    print LOG(@f)     
    --var ok
    --print 'ok'
END TRY

BEGIN CATCH             
    IF (@trans > 0 AND XACT_STATE() <> -1)
    BEGIN
        PRINT 'ROLLBACK SavePoint'
        ROLLBACK TRANSACTION SavePoint
    END
    PRINT 'Error'
END CATCH
END

然后执行

BEGIN TRANSACTION   
EXEC DoSomething 

IF XACT_STATE() = -1      
BEGIN   
    PRINT 'ROLLBACK XACT'
    ROLLBACK 
END

IF @@TRANCOUNT > 0 
BEGIN
    PRINT 'COMMIT'
    COMMIT 
END

【讨论】:

    猜你喜欢
    • 2021-05-23
    • 2015-06-23
    • 2015-12-21
    • 2018-03-11
    • 2012-02-18
    • 1970-01-01
    • 2016-06-21
    • 1970-01-01
    • 2014-03-22
    相关资源
    最近更新 更多