我正在编写一个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)锁?
答案 0 :(得分:5)
你说:
我不想阻止别人 阅读表格的流程,但是 我确实想阻止其他进程 更新表格。
您只需在TXN的持续时间内使用共享读锁定。这意味着没有其他进程可以与TABLOCK一起获得“写”锁。而且你也不需要COUNT。
...
BEGIN TRANSANCTION
SELECT TOP 1 KeyCol FROM TheTable WITH (TABLOCK, HOLDLOCK)
...
为什么你认为你想要一个更新锁?
相当于SERIALIZABLE。更多 信息,请参阅稍后的SERIALIZABLE 这个话题。 HOLDLOCK仅适用于 它所在的表格或视图 指定且仅在持续时间内 由...定义的事务 它用于的声明。 ... 使共享锁更具限制性 持有他们直到交易 完成,而不是释放 必要时尽快共享锁定 表或数据页不再 需要,交易是否有 已完成或未完成。
在评论后编辑:
您无法指定“独占锁定”和允许其他进程读取。这些概念是相互排斥的。您希望阻止对整个表的写入,持久共享/读取锁将执行此操作。这就是SERIALIZABLE的用武之地。
共享锁
......别的 事务可以修改数据 共享(S)锁存在于 资源。共享(S)锁定 资源尽快释放 读取操作完成,除非 事务隔离级别设置为 可重复读或更高,或a 锁定提示用于保留 共享(S)锁持续时间 交易。
所以:共享锁不允许写入,可以通过将其设置为SERIALIZABLE来保持写入
答案 1 :(得分:1)
TABLOCK
指定对表执行锁定并保持到语句结束。如果正在读取数据,则会执行共享锁定。如果正在修改数据,则会执行独占锁定。如果还指定了HOLDLOCK,则会保持共享表锁定,直到事务结束。
当与OPENROWSET批量行集提供程序一起使用以将数据导入到没有索引的表中时,TABLOCK允许多个客户端通过优化的日志记录和锁定将数据同时加载到目标表中。
取自:http://msdn.microsoft.com/en-us/library/ms187373(SQL.90).aspx