当前位置: 首页 > 知识库问答 >
问题:

在 catch 块中插入导致错误:无法提交当前事务,并且不支持写入日志文件的操作

柳修为
2023-03-14

我有两个过程,一个外部过程和一个内部过程,我想了解错误处理的行为。内部过程引发错误,并尝试将 catch 块中的某些内容插入到表中。之后,将引发错误,将其传递给外部过程,然后应回滚事务。

我试图理解为什么我的代码会抛出错误消息:

Msg 50000, Level 11, State 1, Procedure dbo.OuterProcedure, Line 21 [Batch Start Line 9]
The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction.

我希望看到以下消息:

Msg 50000, Level 11, State 1, Procedure dbo.OuterProcedure, Line 21 [Batch Start Line 9]
Error converting data type varchar to numeric.

我知道问题来自内部过程中的 catch 块,发生这种情况是因为我试图在引发错误之前将某些内容插入到日志表中。当我切换这些语句或删除插入时,我收到实际的错误消息。我也知道,在内部过程和无论如何都会回滚的事务中进行日志记录是不明智的。

我想了解是什么使这个事务成为“注定”的事务,即使XACT_ABORT被设置为off。

完整代码:

我的主要程序是:

CREATE PROCEDURE [dbo].[OuterProcedure]
AS
BEGIN
    SET XACT_ABORT OFF;

    BEGIN TRY
        BEGIN TRANSACTION ;

        -- do other stuff 

        EXEC [dbo].[innerprocedure];

        -- do other stuff 

        COMMIT TRANSACTION ;
    END TRY

    BEGIN CATCH
        ROLLBACK TRANSACTION;

        DECLARE @ErrText NVARCHAR(2000);
        SET @ErrText = ISNULL(ERROR_MESSAGE(), 'nothing')
        RAISERROR(@ErrText, 11, 1) WITH NOWAIT
    END CATCH;

END;

我内心的程序:

CREATE PROCEDURE [dbo].[InnerProcedure]
AS
BEGIN
    SET XACT_ABORT OFF;
    SET NOCOUNT ON;
    
    BEGIN TRY
    -- do other stuff 

    -- provoke error
        SELECT 
              CASE
                  WHEN 1 = 0
                  THEN 0.0
                  ELSE ''
              END;

    -- do other stuff 
    END TRY
    BEGIN CATCH

        DECLARE @ErrText NVARCHAR(2000);

        SELECT 
              @ErrText = ISNULL(ERROR_MESSAGE(), 'nothing');

        INSERT INTO [dbo].[logtable]
        ( 
              [Message]
            , [ErrNr]
        ) 
        VALUES
        ( @ErrText
        , -1
        );

        RAISERROR(@LogText, 11, 0) WITH NOWAIT;
    END CATCH;
END;

共有1个答案

鱼志学
2023-03-14

我想了解是什么使这个事务成为“注定”的事务,即使XACT_ABORT被设置为off。

XACT_STATE() 在 catch 块中为 -1,因此事务注定要失败。

  SELECT 
      CASE
          WHEN 1 = 0
          THEN 0.0
          ELSE ''
      END;

抛出错误

数据类型varchar转换为数字时出错。

“大多数转换错误”是Erland Sommarskog将其归入错误类别的错误类型之一。

带回滚的批处理中止这是SQL Server对用户错误做出的最强烈的反应。如果堆栈上没有CATCH处理程序,这些错误会当场中止执行,并且还会回滚任何打开的事务。如果有CATCH处理程序,错误会被捕获,但任何打开的事务都是注定要失败的,必须回滚。无论XACT中止是开还是关,行为都是一样的。

错误行为的分类有些神秘,没有记录,也不直观。阅读他的文章了解更多细节。

 类似资料:
  • 我希望在出现错误时回滚数据的事务,同时将错误写入数据库。 我不能处理事务注释。 下面的代码生成一个运行时错误(1/0),并且仍然将数据写入数据库。并将数据写入错误表。 在StackOverflow中,我尝试了几种变体,并遵循类似的问题,但没有成功。 谁有一个提示,怎么办?

  • 我的grails配置log4j部分中有以下内容: 文件“onetract3.log”已成功创建,但未向该文件写入任何内容。 我可以在控制台中看到信息处理正确。 Grails版本是2.3.5 知道为什么这没有写入日志文件吗? 编辑:10.03.1014,设置相加为false。

  • 问题内容: 我正在尝试配置log4j以将消息记录到文件中。现在,确实使用我提供的名称创建了该文件,但是日志未写入该文件。我的代码: 我文件的内容: 运行此命令时,将在控制台中获得以下输出: 该文件确实在我的主目录中创建。但是它是空的。 有什么想法我做错了吗?我正在使用log4j 1.2.17版。 问题答案: 输出似乎是Java标准日志记录框架(JUL)发出的默认格式。 因此,有两种可能性(想到):

  • 我正在使用带有log4j2的Spring Boot1.5.9,当我测试日志记录功能时,创建了日志文件,但没有将日志写入其中,而控制台日志记录程序运行良好。请在pom.xml&log4j2.properties配置下面找到。 log4j2.properties文件:

  • 问题内容: 好的,这是我设置所有内容的代码: 发生的是 error.log被创建 没有写任何东西 尽管未添加StreamHandler并将debug设置为false,但我仍然将所有内容都添加到STDOUT中(这可能是正确的,但仍然看起来很奇怪) 我是完全离开这里还是发生了什么事? 问题答案: 为什么不这样做呢? 如果现在启动应用程序,你将看到error.log包含: 有关更多信息,请访问http:

  • 问题内容: 有什么方法可以将错误日志或异常写入Java文件中。我已经通过Log4j。我用谷歌搜索,但是努力找到了一个好的解决方案。我写了一个简单的代码 还有其他方法可以记录错误或异常吗?有谁可以向我提供Log4j的示例示例? 问题答案: 首先阅读log4j手册,配置滚动日志文件很容易。您不必执行任何显式的文件操作。 其次,每当您遇到异常时,都应这样做 值得阅读手册。甚至最好阅读完整的log4j手册