我有一个存储过程似乎正在意外退出。我尝试在存储过程中进行捕获,但是从未击中该代码。从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。
有什么方法可以找出导致存储过程退出的原因?我阅读的链接之一表明,将调用包装到存储过程中的另一个调用将捕获通常会遇到的任何其他错误,但我也看不到任何错误。
在这种情况下,问题在于命令超时。第二条插入语句大约需要35秒,命令超时设置为30秒。当超时发生时,SQL Server只会杀死存储的proc。