在SQL Server中的存储过程开始时获取更新表锁定

时间:2010-06-04 10:57:17

标签: sql-server-2005 locking

我正在编写一个SQL Server存储过程,我想在执行存储过程的主体之前锁定表以进行更新。我不想阻止其他进程读取表,但我确实希望阻止其他进程更新表。

这是我的第一次尝试:

CREATE PROCEDURE someProcedure
BEGIN
   SET TRANSACTION ISOLATION LEVEL READ COMITTED
   BEGIN TRANSANCTION
     SELECT COUNT(*) FROM TheTable WITH (UPDLOCK, TABLOCK)

     -- Pause procedure so that we can view the locks with sp_lock
     WAITFOR DELAY '00:15'

     -- Do stuff
   COMMIT
END

当我执行存储过程并调用sp_lock时,我看到该表确实已被锁定。但是,它使用Exclusive锁而不是更新锁来锁定:

spid | dbid | ObjId     | IndId | Type | Resource | Mode | Status
------------------------------------------------------------------
63   | 10   | 233208031 | 0     | TAB  |          | X    | GRANT

如何获得更新(U)锁?

2 个答案:

答案 0 :(得分:5)

你说:

  

我不想阻止别人   阅读表格的流程,但是   我确实想阻止其他进程   更新表格。

您只需在TXN的持续时间内使用共享读锁定。这意味着没有其他进程可以与TABLOCK一起获得“写”锁。而且你也不需要COUNT。

...
   BEGIN TRANSANCTION
     SELECT TOP 1 KeyCol FROM TheTable WITH (TABLOCK, HOLDLOCK)
...

为什么你认为你想要一个更新锁?

HOLDLOCK or SERIALIZABLE

  

相当于SERIALIZABLE。更多   信息,请参阅稍后的SERIALIZABLE   这个话题。 HOLDLOCK仅适用于   它所在的表格或视图   指定且仅在持续时间内   由...定义的事务   它用于的声明。   ...   使共享锁更具限制性   持有他们直到交易   完成,而不是释放   必要时尽快共享锁定   表或数据页不再   需要,交易是否有   已完成或未完成。

在评论后编辑:

  • “exclusive lock”表示“只使用数据的一个进程”。
  • “SERIALIZABLE”基本上意味着持有锁(共享,独家,等等)更长时间。

您无法指定“独占锁定”允许其他进程读取。这些概念是相互排斥的。您希望阻止对整个表的写入,持久共享/读取锁将执行此操作。这就是SERIALIZABLE的用武之地。

来自"Lock Modes"

  

共享锁

     

......别的   事务可以修改数据   共享(S)锁存在于   资源。共享(S)锁定   资源尽快释放   读取操作完成,除非   事务隔离级别设置为   可重复读或更高,或a   锁定提示用于保留   共享(S)锁持续时间   交易。

所以:共享锁不允许写入,可以通过将其设置为SERIALIZABLE来保持写入

答案 1 :(得分:1)

TABLOCK

指定对表执行锁定并保持到语句结束。如果正在读取数据,则会执行共享锁定。如果正在修改数据,则会执行独占锁定。如果还指定了HOLDLOCK,则会保持共享表锁定,直到事务结束。

当与OPENROWSET批量行集提供程序一起使用以将数据导入到没有索引的表中时,TABLOCK允许多个客户端通过优化的日志记录和锁定将数据同时加载到目标表中。

取自:http://msdn.microsoft.com/en-us/library/ms187373(SQL.90).aspx