我有一個存儲過程在生產中做了2件事情。它更新一個表格,然後將記錄插入另一個表格。第一步(更新)似乎發生,但我們通過檢查第二步未發生的數據找到了實例。我查看了數據並確認它不是數據問題。我已確認查詢返回適當的數據以確保查詢完成,並且在正常情況下兩者都應該執行。我不知道是否可能存在某種性能問題......或阻止第二步發生的問題阻止該步驟的發生。如何調試我無法在任何測試環境中重現的SQL Server數據問題?
存儲過程的錯誤處理如下。
BEGIN TRY
BEGIN TRANSACTION;
-- perform update to data
-- insert record into second table.
IF (@@ERROR = 0 AND @@TRANCOUNT > 0)
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK TRANSACTION;
END
DECLARE @WebSafeErrorId INT;
EXEC dbo.spErrorInsert @WebSafeErrorId OUTPUT, 'Proc';
-- Reraise the error back to the client.
IF (@WebSafeErrorId != 0)
BEGIN
DECLARE @Error VARCHAR(20);
SET @Error = CAST(@WebSafeErrorId AS VARCHAR(20));
RAISERROR(@Error, 11, 1);
END
ELSE
BEGIN
RAISERROR('An error has occurred but there is no error to log.', 11, 1);
END
END CATCH;
當然,如果在此過程中發生的錯誤導致插入不發生它將被記錄,然後引發。對於spErrorInsert的代碼如下...
CREATE PROCEDURE [dbo].[spErrorInsert]
@ReturnErrorId INT OUTPUT
, @ErrorSourceType VARCHAR(4) = NULL
, @ParentErrorId INT = NULL
, @StackTrace VARCHAR(MAX) = NULL
AS
SET NOCOUNT ON;
--SET XACT_ABORT ON;
-- Will indicate an error was not logged.
SET @ReturnErrorID = 0;
DECLARE
@ErrorSource VARCHAR(200)
, @ErrorMessage VARCHAR(MAX)
, @ComposedErrorMessage VARCHAR(MAX)
, @ErrorLine INT
, @ErrorSeverity INT
, @ErrorState INT
, @ErrorNumber INT;
SET @ErrorSource = ERROR_PROCEDURE();
SET @ErrorMessage = ERROR_MESSAGE();
SET @ErrorLine = ERROR_LINE();
SET @ErrorSeverity = ERROR_SEVERITY();
SET @ErrorState = ERROR_STATE();
SET @ErrorNumber = ERROR_NUMBER();
SET @ComposedErrorMessage = 'Message: Error occurred in procedure ' + CAST(@ErrorSource AS VARCHAR(MAX))
+ ' on line ' + CAST(@ErrorLine AS VARCHAR(MAX))
+ '. Error: ' + @ErrorMessage;
BEGIN TRY
INSERT INTO Errors(
ParentId
, ErrorSourceType
, ErrorSource
, [Message]
, [LineNo]
, Severity
, Stacktrace
, ts)
VALUES (@ParentErrorId
, @ErrorSourceType [email protected] --- NOTE: move this into a parameter ...
, @ErrorSource
, @ComposedErrorMessage
, @ErrorLine
, @ErrorState
, @Stacktrace
, GETDATE()
);
SET @ReturnErrorId = SCOPE_IDENTITY();
END TRY
BEGIN CATCH
RAISERROR('An error has occurred but there is no error to log.', 11, 1);
END CATCH;
我不知道,也許有辦法讓這是怎麼回事的數據庫在特定時間在某個過程被稱爲快照...我不知道如何確定它是否應該在什麼時候沒有發生?有沒有我可以使用的工具或SQL功能,我不知道?
不要混合和匹配您的錯誤處理過程。如果你使用'TRY ... CATCH',那麼你不需要'@@ ERROR'和'@@ TRANCOUNT'的'IF'檢查 - 如果有錯誤,它會直接跳到你的'CATCH'。 – JNK
如果是我,我會開始記錄開始和停止更新並單獨插入步驟。然後,您可以輕鬆比較,看看您是否曾經開始但並未停止,或跳過一步。 – JNK
記錄開始和停止實際上不是一個壞主意... –