我有一个表,用于保存客户端的连接和断开连接时间。
ID int
ClientID int
BeginDate datetime
EndDate datetime
连接客户端时,会创建一个Session
记录,其EndDate
为空。
INSERT Session(ClientID, BeginDate, EndDate)
VALUES(@ClientID, GETDATE(), null)
当客户端断开连接时,我会更新会话,因此EndDate
包含断开连接时间。
UPDATE Session
SET EndDate = GETDATE()
WHERE Id = @SessionID
但这并不总是被召唤。
因此,为了确保同一个客户端不会同时拥有多个会话,我会在插入新会话之前运行此查询。
UPDATE Session
SET EndDate = GETDATE()
WHERE ClientID = @ClientID
and EndDate is null
根据deadlock graph,当多个客户端同时连接时会导致死锁。
我不明白为什么会导致死锁, 我甚至不明白为什么这个查询需要锁定 我做错了什么?
答案 0 :(得分:1)
一个更新语句使得X锁定,对于这个语句甚至可能是一个页面锁定或一个表锁定,您可以尝试选择打开会话的id并使用in执行这些更新-clause之后,更有可能只锁定那些行。这也取决于你的隔离级别。
方式不能打开多个会话,如果(并且我猜测它是一个网络应用程序)用户使用2个不同的网络浏览器打开网站。
答案 1 :(得分:1)
每次插入之前更新EndDate似乎不是一个好主意。即使没有更新,您也可以锁定表。在更新之前,您应该检查是否有任何会话,其中endate为null。您可以使用NoLock提示进行阅读 未提交的数据。
执行此检查可以最大程度地减少此查询导致的锁定。预防胜于治疗:)