小编Max*_*pov的帖子

从连接表中选择时如何避免死锁?

我有两个非常简单的表,让我们称它们为[UserData1]和[UserData2].它们都有[UserId]列作为主键.我正在针对这两个表运行两种类型的查询.一个是SELECT语句,它返回特定用户的组合数据:

SELECT <a subset of columns from both tables>
FROM [UserData1] ud1
    FULL OUTER JOIN [UserData2] ud2 ON ud1.[UserId] = ud2.[UserId]
WHERE
    ud1.[UserId] = @UserId OR ud2.[UserId] = @UserId
Run Code Online (Sandbox Code Playgroud)

另一个是为特定用户更新两个表中的用户数据的事务:

BEGIN TRANSACTION

UPDATE [UserData1]
SET <new values>
WHERE [UserId] = @UserId

UPDATE [UserData2]
SET <new values>
WHERE [UserId] = @UserId

COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)

这里的问题是SELECT语句中获取共享表锁的顺序是不确定的,如果SQL Server决定在[UserData1]之前锁定[UserData2],这可能(并且实际上)会导致传统的死锁情况.在这种情况下,避免死锁的最佳方法是什么?

将这些表合并到一个表中,对吗?我希望这很容易.假设有理由将它们分开.

READ UNCOMMITTED/NOLOCK提示?假设不能容忍脏读.

SNAPSHOT隔离级别?这样可以解决问题,但我不确定所涉及的开销.

所以问题归结为:有没有办法保证获取连接表的锁定顺序?

起初我认为这可以通过FORCE ORDER查询提示来实现,但后来我通过实验发现它不一定强制执行表被锁定的顺序.在这种特殊情况下的另一个解决方案是为每个表发出单独的SELECT查询,然后在应用程序层中组合两个单行记录集,但是如果我需要为多个用户进行查询,我仍然希望得到所有导致一个记录集.

更新:

这是死锁跟踪的摘录:

   Deadlock encountered .... Printing deadlock information
   Wait-for graph

   Node:1
   KEY: 17:72057594039173120 (e21762ccf3dc) CleanCnt:3 Mode:X …
Run Code Online (Sandbox Code Playgroud)

sql-server

8
推荐指数
1
解决办法
1609
查看次数

标签 统计

sql-server ×1