Jim*_*rne 2 locking sql-server-2005
我正在编写一个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
Run Code Online (Sandbox Code Playgroud)
当我执行存储过程并调用sp_lock时,我看到表确实已被锁定.但是,它使用Exclusive锁而不是更新锁锁定:
spid | dbid | ObjId | IndId | Type | Resource | Mode | Status
------------------------------------------------------------------
63 | 10 | 233208031 | 0 | TAB | | X | GRANT
Run Code Online (Sandbox Code Playgroud)
我怎样才能获得更新(U)锁?
你说:
我不想阻止其他进程读取表,但我确实希望阻止其他进程更新表.
在TXN的持续时间内,您只需要一个共享读锁定.这意味着没有其他进程可以与TABLOCK一起获得"写"锁.而且你也不需要COUNT.
...
BEGIN TRANSANCTION
SELECT TOP 1 KeyCol FROM TheTable WITH (TABLOCK, HOLDLOCK)
...
Run Code Online (Sandbox Code Playgroud)
为什么你认为你想要一个更新锁定?
相当于SERIALIZABLE.有关更多信息,请参阅本主题后面的SERIALIZABLE.HOLDLOCK仅适用于指定它的表或视图,并且仅适用于由其使用的语句定义的事务的持续时间....通过保持共享锁限制直到事务完成,而不是无论事务是否已完成,一旦不再需要所需的表或数据页,就立即释放共享锁.
评论后编辑:
您不能指定"独占锁定" 并允许其他进程读取.这些概念是相互排斥的.您希望防止写入整个表,持久共享/读取锁将执行此操作.这就是SERIALIZABLE的用武之地.
共享锁
...当资源上存在共享(S)锁时,没有其他事务可以修改数据.一旦读取操作完成,就释放资源上的共享(S)锁,除非事务隔离级别设置为可重复读取或更高,或者使用锁定提示在持续时间内保留共享(S)锁定.交易.
所以:共享锁不允许写入,并且可以通过使其成为SERIALIZABLE来保持写入