什么时候UPDLOCK在SQL服务器上发布?

时间:2017-08-16 03:48:35

标签: sql-server transactions locking database-administration query-hints

最近我在SQL服务器中使用了Hints和Locks。虽然谷歌关于这个话题,我已经阅读了一个博客,其中一些查询已经编写,我不是很难理解。这是

BOL声明:在读取表时使用更新锁而不是共享锁,并保持锁直到语句或事务结束。我在翻译时遇到了一些麻烦。这是否意味着在执行SELECT语句后释放更新锁,除非事务中的SELECT语句?

换句话说,我在以下2个场景中的假设是否正确?

场景1:无交易

BEGIN TRANSACTION 
SELECT something FROM table WITH (UPDLOCK)

/* some code, including an UPDATE */
COMMIT TRANSACTION

/* update locks released */

场景2:使用交易

BEGIN TRAN

SELECT Id FROM Table1 WITH (UPDLOCK)
WHERE AlertDate IS NULL;

UPDATE Table1 SET AlertDate = getutcdate() 
WHERE AlertDate IS NULL;

COMMIT TRAN 

方案2的示例(参考stackoverflow博客)

UPDLOCK

请帮助理解上述问题。

我的第二个问题是:一旦同时完成选择语句的执行Symbol是否被释放?

2 个答案:

答案 0 :(得分:2)

您在方案2中的假设是正确的。

要回答你的第二个问题,不。更新锁保留在所选行上,直到事务结束,或者直到更新语句修改这些行时转换为独占锁。使用SSMS逐个查看每个语句以进行验证。

BEGIN TRAN
    -- execute sp_lock in second session - no locks yet
    SELECT Id FROM Table1 WITH (UPDLOCK) WHERE AlertDate IS NULL;
    -- execute sp_lock in second session - update locks present
    UPDATE Table1 SET AlertDate = getutcdate() WHERE AlertDate IS NULL;
    -- execute sp_lock in second session - update (U) locks are replace by exclusive locks (X) for all row(s) returned by SELECT and modified by the UPDATE (Lock Conversion).
    -- Update locks (U) continue to be held for any row(s) returned by the SELECT but not modified by the UPDATE
    -- exclusive locks (X) are also held on all rows not returned by SELECT but modified by UPDATE. Internally, lock conversion still occurs, because UPDATE statements must read and write.
COMMIT TRAN 

    -- sp_lock in second session - all locks gone.

对于场景1中发生的事情,所有T-SQL语句都存在于隐式或显式事务中。 Senario 1含蓄地说:

BEGIN TRAN
     SELECT something FROM table WITH (UPDLOCK)
     -- execute sp_lock in second session - update locks (U) will be present
     COMMIT TRAN;
     -- execute sp_lock in second session - update locks are gone.

答案 1 :(得分:0)

  

这是否意味着在执行SELECT语句后释放更新锁,除非事务中的SELECT语句?

一旦读取行,锁就会被释放..但是锁定保持将是U锁定,因此任何试图修改它的并行事务都必须等待

如果在事务中将select包装在上面,则只有在事务提交时才会释放锁,因此任何并行事务获取锁与U锁不兼容都必须等待

begin tran
select * from t1 with (updlock)

以下第二种情况

BEGIN TRANSACTION 
SELECT something FROM table WITH (UPDLOCK)

/* some code, including an UPDATE */
COMMIT TRANSACTION

想象一下,如果你的select查询返回了100行,那么所有人都会使用U锁,并想象同一事务中的更新会影响2行,这两行将转换为x锁。现在你的在提交事务之前,查询将具有98个u锁和2个x

我想将Updlock视为可重复读取,可以添加任何新行,但任何并行事务都无法删除或更新现有行