您可以强制 SQL 存储过程按给定顺序获取锁吗

Posted

技术标签:

【中文标题】您可以强制 SQL 存储过程按给定顺序获取锁吗【英文标题】:Can you force a SQL Stored Procedure to take locks in a given order 【发布时间】:2009-09-09 04:12:02 【问题描述】:

我有两个存储过程,其中一个被调用很多,因此非常简单并且执行得很好。此外,即使它们是可序列化的,它们实际上也可以很好地并行工作。

但是,我有第二个查询,它只在某些情况下被调用,在接触同一张表之前需要做更多的检查。问题是,当您并行运行这些程序时,最终会出现死锁,因为每个存储的 proc 以不同的顺序锁定。

我的问题是您能否强制给定的存储过程以特定顺序锁定以匹配您的重要查询?这样他们就不会死锁并很好地执行:)。

编辑: 作为澄清,我希望我的第二个程序做的是这个。

--Lock table1
--Lock table2

--Perform query.

【问题讨论】:

【参考方案1】:

您可以为此提供Table Hints。

来自 MSDN:

表提示在数据操作语言 (DML) 语句期间通过指定锁定方法、一个或多个索引、查询处理操作(如表扫描或索引查找)覆盖查询优化器的默认行为,或者其他选项。

只是非常非常小心,因为它非常很容易搞砸......

例如:

SELECT Id FROM MyTable WITH UPDLOCK

将在 MyTable 上获取更新锁,直到事务完成。

有多种提示可用于不同类型的锁。使用任何合适的东西。

【讨论】:

【参考方案2】:

如果您的 2nd proc 在执行查询之前需要锁定 2 个表,我认为这不是导致问题的锁定顺序,它只是 2 个 procs 之间的直接死锁。

您是否尝试过快照隔离?它可能不适合您的情况,但可以缓解锁定问题。

还可以调查应用程序锁(在 BOL 中查找 sp_getapplock/sp_releaseapplock)。

使用表格提示控制所占用的锁,我认为不会解决您的问题。

恕我直言,99% 的死锁可以通过索引解决,而不是搞乱隔离级别、升级锁或应用程序锁 - 再次可能对您没有帮助,但如果没有任何进一步的细节,这很难说。

【讨论】:

快照隔离的完美候选者。当 MS 决定使用快照隔离实现 MSDTC 事务时,请告诉我。 对于锁,在一个事务中多次运行同一个 SProc 是可行的。运行多个也可以,因为它们不会死锁,第一个运行,第二个阻塞,直到它获得锁。但是如果同时运行 sproc 1 和 sproc 2,那么每个都以不同的顺序获取锁,然后死锁。因此,我为什么要控制 SProc2 上的锁定顺序,这样我就可以让它们阻塞并执行它们的工作,而不是让所有东西都死锁。 MSDTC - 这是从哪里来的?您是否在不同的服务器上运行 procs?远程查询?我仍然不明白你所说的锁的顺序是什么意思。没有看到任何代码都很难..... 我明白这一点。 DTC 是由于数据库写入涉及辅助系统。实际上,我必须发送消息并将发送的消息标记为事务(涉及 $$$)。第二个过程是一个特例。锁定是由于 tran 顺序。我什至不能在没有死锁的情况下在同一个事务中混合两种不同的事务类型。 所以我猜应用程序锁定建议也失败了,因为它是跨服务器的?

以上是关于您可以强制 SQL 存储过程按给定顺序获取锁吗的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 获取解析的查询

用于获取表名、视图和存储过程的 SQL 语句,按模式排序

怎么知道 oracle存储过程是不是执行完

如何强制 s-s-rS 参数的值按输入的顺序运行?

在 SnowFlake DB 中并行执行存储过程中的 SQL 语句

存储过程返回一个数组;如何在 SQL 中使用?