我的Windows服务,偶尔用C#编写(每周几次)记录这样的消息:
getClientData:事务(进程ID ###)在锁定时死锁 资源与另一个进程并被选为死锁 受害者。重新运行该交易。
getClientData
是我自己的C#函数,只调用存储过程。存储过程是mssql中优先级+挂起队列的实现。我从here得到了这个想法。
我刚刚找到了this解释如何在没有简单选择查询中的事务的情况下发生死锁(+后台发生的其他事情)。现在,这些死锁并不是那么重要,因为这不会导致我的服务崩溃(我只是重试查询),但我想知道是否可以摆脱这些死锁。
哦,并且,数据从几个不同的来源一次一行地插入到[dbo].[tbl_client_data]
表中(但它们都只是简单的一行插入)。
存储过程看起来非常像这样(有更多数据列,但这似乎与我无关):
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
所以我的问题是 - 有没有办法摆脱这些偶然的(非常罕见的)死锁,或者我应该忽略它们,只是按照我的知识重试查询?