【问题标题】:Release lock on first table during stored procedure在存储过程期间释放第一个表上的锁
【发布时间】:2020-04-26 08:47:53
【问题描述】:

我遇到了一个看似简单但找不到解决方案的问题。我有一个长时间运行的存储过程,它将在语句的开头和结尾更新一个表。问题是,表在整个过程中都被锁定了。这是一个简化的版本:

ALTER PROCEDURE [dbo].[Proc_FullRefresh]
AS
BEGIN
    UPDATE Settings SET SettingValue = 'true' WHERE SettingName = 'Running' 

    WAITFOR DELAY '00:00:30'
END

问题是,在整个过程运行时,我无法从Settings 表中选择该行。我什至尝试包装交易以查看是否有帮助:

BEGIN TRAN
UPDATE Settings SET SettingValue = 'true' WHERE SettingName = 'Running' 
COMMIT;

BEGIN TRAN
WAITFOR DELAY '00:00:30'
COMMIT

但这也没有用。有什么方法可以在过程执行其他操作时释放Settings 表上的锁?

【问题讨论】:

  • 另外 - 即使您在事务中运行更新,极不可能整个表都会被锁定; SQL Server 使用 基于行的 锁 - 因此您正在更新的行可能被锁定 - 但不是整个表 ....

标签: sql-server tsql sql-server-2012 locking


【解决方案1】:

在程序执行其他操作时,有什么方法可以释放设置表上的锁定?

您正在事务中运行存储过程,否则 UPDATE 语句将立即完成,并且在其他会话中可见。当您添加额外的 BEGIN TRAN/COMMIT 对时,您实际上是在创建一个“嵌套事务”。来自 UPDATE 的锁将一直保持到外部(实际)事务的提交。

所以不要在事务中运行该过程。

一些客户端和数据访问/ORM 框架自动启动事务,但大多数要求您显式启动事务。

【讨论】:

  • 该行在有更新锁的情况下仍然无法读取,即使没有事务。
  • 如果没有事务,任何更新锁都将在 UPDATE 语句之后释放,因为每个语句都在自己的事务中运行。
  • 卫生署!我怎么没有意识到最外面的BEGINEND 本身就是一个事务?在这里,我认为它只是在说“这是存储过程的开始和结束”。删除 BEGINEND 后,它按预期工作。非常感谢!
  • 没有。存储过程 BEGIN AND END 不创建事务。我的意思是你有一个事务在之前存储过程运行。
  • 抱歉,我的测试过激了。 WAITFOR 只是模拟我所有长时间运行的命令(以保持问题简洁)。您对自动启动交易的客户的编辑实际上帮助指导了我。我正在执行来自 EF 的程序(很抱歉遗漏了那个细节)。将TransactionalBehavior.DoNotEnsureTransaction 添加到调用 DID 实际上可以让一切正常工作。谢谢!
猜你喜欢
  • 2010-11-02
  • 1970-01-01
  • 2017-12-25
  • 2016-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多