My windows service, written in C# occasionally (few times a week) logs a message like this:
getClientData: Transaction (Process ID ###) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
getClientData
is my own C# function that simply calls a stored procedure. The stored procedure is an implementation of priority+pending queue in mssql. I got the idea from here.
I have just found this explanation of how a deadlock can happen without transactions in a simple select query (+additional things happening in background). Now, these deadlocks aren't really that big of a deal, because that does not crash my service (i simply retry the queries), but I would like to know if it's possible to get rid of these deadlocks.
Oh and, the data is inserted into [dbo].[tbl_client_data]
table one row at a time from several different sources (they are all just simple one row inserts, though).
Stored procedure looks pretty much like this (there are more data columns, but that seems irrelevant to me):
CREATE PROCEDURE [dbo].[sp_get_client_data]
@client_id [int],
@limit [int] = 0
AS
BEGIN
IF(@limit < 0) SET @limit = 0;
DECLARE @data TABLE
(
[id] [int],
[data] [varchar](max),
[client_id] [int],
[ts] [datetime],
[priority] [tinyint]
);
IF(@limit > 0)
BEGIN
DELETE TOP(@limit)
FROM [dbo].[tbl_client_data]
OUTPUT DELETED.[id]
,DELETED.[data]
,DELETED.[client_id]
,DELETED.[ts]
,DELETED.[priority]
INTO @data
WHERE [id] IN (SELECT TOP(@limit) [id]
FROM [dbo].[tbl_client_data] with(nolock)
WHERE ([ts] IS NULL OR [ts] <= GETDATE())
AND [client_id] = @client_id
ORDER BY [priority], [ts]);
END
SELECT *
FROM @data
ORDER BY [priority], [ts];
END
So my question is - Is there a way to get rid of these occasional (very rare) deadlocks, or should I just ignore them and simply retry the queries as I do know?