Hi all,
I have a number of stored procedures that are called in parallel by SSIS to rebuild tables during an overnight process in a data warehouse. I am using a common table (named PL_ProcessLog) to log when each sproc starts and ends. I am getting locks occuring on PL_ProcessLog as several sprocs try and create a row in this table at the same time. The code to insert into this table is in a sproc of its own, which is wrapped in a tight transaction each time it is called.
The sproc that inserts a row in the log table is:
USE lib GO IF OBJECT_ID(N'dbo.PL_LogProcessStart', N'P') IS NOT NULL DROP PROCEDURE PL_LogProcessStart GO CREATE PROCEDURE dbo.PL_LogProcessStart @ComponentName NVARCHAR(100), @ProcessName NVARCHAR(100), @StepName NVARCHAR(100), @ID UNIQUEIDENTIFIER OUTPUT AS SET @ID = NEWID() --SET @StepName = @StepName + ' (SPID:' + CAST(@@SPID AS VARCHAR(4)) + ')' INSERT PL_ProcessLog WITH (ROWLOCK) (Identifier, ComponentName, ProcessName, StepName, StartDate) VALUES (@ID, @ComponentName, @ProcessName, @StepName, GETDATE()) OPTION (MAXDOP 1) GO
The calling code all looks as below, in this instance I am showing one called PMI_PopulateNameHistory, but they all take the same framework:
USE DW GO IF OBJECT_ID('dbo.PMI_PopulateNameHistory', 'P') IS NOT NULL DROP PROCEDURE dbo.PMI_PopulateNameHistory GO CREATE PROCEDURE dbo.PMI_PopulateNameHistory /* Clears down and repopulates the name history table. Depends on: camis.pmi.pmi_othernames DW..PMI_Patient */ AS DECLARE @ID UNIQUEIDENTIFIER DECLARE @ID2 UNIQUEIDENTIFIER DECLARE @Message NVARCHAR(1000) DECLARE @ErrorSeverity INT DECLARE @ErrorState INT BEGIN TRY BEGIN TRANSACTION EXEC lib.dbo.PL_LogProcessStart 'PMI', 'PMI_PopulateNameHistory', 'PMI_PopulateNameHistory', @ID OUTPUT COMMIT TRANSACTION BEGIN TRANSACTION /* code to rebuild a table */ COMMIT TRANSACTION BEGIN TRANSACTION EXEC lib.dbo.PL_LogProcessEnd @ID COMMIT TRANSACTION END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION SET @Message = ERROR_MESSAGE() SET @ErrorSeverity = ERROR_SEVERITY() SET @ErrorState = ERROR_STATE() BEGIN TRANSACTION EXEC lib.dbo.PL_LogProcessFail @ID, @Message COMMIT TRANSACTION RAISERROR(@Message, @ErrorSeverity, @ErrorState) END CATCH GO
The deadlock is occurring when two sprocs call PL_LogProcessStart at the same time. They deadlock each other. How can this be? They're both simply inserting one row, and the call is in a tight transaction. More widely, is there anything I could improve about the error handling/process logging above?
Any advice gratefully received. Thanks,
Mark
Mark Roworth
Mark Roworth