Перехват хранимой процедуры SQL Server, которая неожиданно завершает работу - PullRequest
1 голос
/ 31 октября 2019

У меня есть хранимая процедура, которая, кажется, неожиданно завершает работу. Я попытался поймать внутри хранимой процедуры, но этот код никогда не ударил. Запуск хранимой процедуры (spInner) вручную из SQL Server Management Studio приводит к тому, что она работает должным образом. Когда хранимая процедура (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 insert». Код просто выходит в этот момент. В журнал ошибок не записывается никаких ошибок, дополнительные журналы «servererror» никогда не записываются. В вызывающем приложении нет исключения. Это похоже на то, что в хранимой процедуре вместо второй вставки есть оператор return.

Можно ли как-нибудь выяснить, что вызывает выход из хранимой процедуры? Одна из ссылок, которые я прочитал, указала, что перенос вызова к хранимой процедуре в другой вызов может перехватить любые дополнительные ошибки, которые обычно выпадают, но я не вижу ни одной из них.

1 Ответ

1 голос
/ 31 октября 2019

В этом случае проблема заключалась в том, что команда истекла. Второй оператор вставки занимал приблизительно 35 секунд, а время ожидания команды было установлено равным 30 секундам. Сервер SQL просто убивает сохраненный процесс, когда истекает время ожидания.

...