捕获正在意外退出的SQL Server存储过程

问题描述 投票:0回答:1

我有一个存储过程似乎正在意外退出。我尝试在存储过程中进行捕获,但是从未击中该代码。从SQL Management Studio手动运行存储过程(spInner)会使它按预期方式工作。当从我的应用程序中调用存储过程(spInner)时,它是从另一个存储过程(spOuter)内部调用的。当我进行手动测试时,我没有这样做,但这不会影响结果,也不会影响日志记录。

CREATE PROCEDURE [dbo].[spInner]
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @NeedsRefresh BIT;
    SET @NeedsRefresh = 0;

    BEGIN TRY  
        INSERT INTO ServerErrors (ErrorMessage, ErrorDateTime) VALUES ('Begin', SYSDATETIME());

        CREATE TABLE #TestPCWorking(...)

        INSERT INTO #TestPCWorking 
            SELECT * FROM ...;

        CREATE TABLE #ActivePCsWorking(...)

        IF EXISTS(SELECT * FROM #TestPCWorking)
        BEGIN
            SET @NeedsRefresh = 1;
            INSERT INTO ServerErrors (ErrorMessage, ErrorDateTime) VALUES ('Before adhoc update', SYSDATETIME());
            UPDATE ...

            -- This statement executes
            INSERT INTO ServerErrors (ErrorMessage, ErrorDateTime) VALUES ('After adhoc update', SYSDATETIME());

            -- This statement executes
            INSERT INTO #ActivePCsWorking
                SELECT ...;  -- This is a big query selecting from #TestPCWorking

            -- This statement executes
            INSERT INTO ServerErrors (ErrorMessage, ErrorDateTime) VALUES ('After first #ActivePCsWorking insert', SYSDATETIME());

            INSERT INTO #ActivePCsWorking
                SELECT ...;  -- This is a different big query selecting from #TestPCWorking;

            -- I never get this message
            INSERT INTO ServerErrors (ErrorMessage, ErrorDateTime) VALUES ('After second #ActivePCsWorking insert', SYSDATETIME());
        END

        INSERT INTO ServerErrors (ErrorMessage, ErrorDateTime) VALUES ('Checking @NeedsRefresh', SYSDATETIME());

        IF (@NeedsRefresh = 1)
        BEGIN
            BEGIN TRANSACTION
            INSERT INTO RealTable 
                SELECT FROM #ActivePCsWorking;
            COMMIT TRANSACTION

            INSERT INTO ServerErrors (ErrorMessage, ErrorDateTime) VALUES ('Never arrives', SYSDATETIME());
        END

        DROP TABLE #ActivePCsWorking;
        DROP TABLE #TestPCWorking;
    END TRY  
    BEGIN CATCH
        -- This message is never added
        INSERT INTO ServerErrors (ErrorMessage, ErrorDateTime) VALUES ('Before rollback error: ' + ERROR_MESSAGE(), SYSDATETIME());
        IF @@TRANCOUNT > 0
            ROLLBACK TRANSACTION;

        INSERT INTO ServerErrors (ErrorMessage, ErrorDateTime) VALUES ('Encountered an error: ' + ERROR_MESSAGE(), SYSDATETIME());

        -- Save the error info
        EXECUTE spGetErrorInfo; -- This logs the error but nothing is logged
    END CATCH;   
END

此存储过程是从另一个存储过程调用的。我也有一个地方:

CREATE PROCEDURE [dbo].[spOuter]
AS
BEGIN
    BEGIN TRY
        EXEC spInner;
    END TRY
    BEGIN CATCH
        INSERT INTO ServerErrors (ErrorMessage, ErrorDateTime) VALUES ('Encountered an error: ' + ERROR_MESSAGE(), SYSDATETIME());

        -- Save the error info
        EXECUTE spGetErrorInfo;  
    END CATCH    
END

我可以看到我的“日志”条目,直到“第一次#ActivePCsWorking插入之后”。该代码就在此时退出。没有错误写入错误日志,永远不会写入额外的“ servererror”日志。调用应用程序中没有引发异常。就像存储的proc具有return语句来代替第二个insert。

有什么方法可以找出导致存储过程退出的原因?我阅读的链接之一表明,将调用包装到存储过程中的另一个调用将捕获通常会遇到的任何其他错误,但我也看不到任何错误。

sql-server stored-procedures sql-server-2014
1个回答
0
投票

在这种情况下,问题在于命令超时。第二条插入语句大约需要35秒,命令超时设置为30秒。当超时发生时,SQL Server只会杀死存储的proc。

© www.soinside.com 2019 - 2024. All rights reserved.