Looking for help solving this deadlock issue... I have a stored proc that is called rather frequently from a number of processes but on a small table (quantity of rows is in low thousands)... Once in a while, I'm getting a deadlock on the proc.
Proc's purpose is to return the next 'eligible for processing' rows. It is very important to not return the same row to two simultaneous calls of the proc.... (that part works fine)... but I can't understand why sometimes there would be a deadlock.
This is a SQL Azure database
Appreciate the help
CREATE PROCEDURE [dbo].[getScheduledAccounts_Monitor]
-- Add the parameters for the stored procedure here
@count int,
@timeout int = 1200,
@forcedAccountId uniqueidentifier = NULL
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
DECLARE @batchId uniqueidentifier
SELECT @batchId = NEWID()
BEGIN TRAN
-- Update rows
UPDATE Schedule
WITH (ROWLOCK)
SET
LastBatchId = @batchId,
LastStartedProcessingId = NEWID(),
LastStartedProcessingTime = GETUTCDATE(),
LastCompletedProcessingId = ISNULL(LastCompletedProcessingId, NEWID()),
LastCompletedProcessingTime = ISNULL(LastCompletedProcessingTime, GETUTCDATE())
WHERE
ActivityType = 'Monitor' AND
IsActive = 1 AND
AccountId IN (
SELECT TOP (@count) AccountId
FROM Schedule
WHERE
(LastStartedProcessingId = LastCompletedProcessingId OR LastCompletedProcessingId IS NULL OR DATEDIFF(SECOND, LastStartedProcessingTime, GETUTCDATE()) > @timeout) AND
IsActive = 1 AND ActivityType = 'Monitor' AND
(LastStartedProcessingTime IS NULL OR DATEDIFF(SECOND, LastStartedProcessingTime, GETUTCDATE()) > Frequency)
ORDER BY (DATEDIFF(SECOND, LastStartedProcessingTime, GETUTCDATE()) - Frequency) DESC
) AND
AccountId = ISNULL(@forcedAccountId, AccountID)
-- Return the changed rows
SELECT AccountId, LastStartedProcessingId, Frequency, LastProcessTime, LastConfigChangeTime, ActivityType
FROM Schedule
WHERE LastBatchId = @batchId
COMMIT TRAN
END
You can use an application lock to ensure single execution. The article below is for SQL 2005 but I am sure the solution applies for newer versions also.
http://www.sqlteam.com/article/application-locks-or-mutexes-in-sql-server-2005