我有以下T-SQL代码:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION T1_Test
/*This is a dummy table used for "locking"
and it doesn't contain any meaningful data.*/
UPDATE lockTable
SET ID = 1
WHERE ID = 1
DECLARE @Count TINYINT
SELECT @Count = COUNT(*)
FROM debugSP
WAITFOR DELAY '00:00:5';
INSERT INTO debugSP
(DateCreated, ClientId, Result)
SELECT
GETDATE(), @@SPID, @Count
COMMIT TRANSACTION T1_Test
我正在使用标记为注释的“锁定”黑客获取独占锁。
注意:使用TABLOCKX或UPDLOCK提示将不起作用,因为我通过拆分语句并在中间添加WAITFOR命令以进行测试来打破ATOMIC-ity。 我不想要那样的东西:
INSERT INTO debugSP (DateCreated, ClientId, Result)
SELECT GETDATE(), @@SPID, COUNT(*)
FROM debugSP
这是运行两个同时会话(带锁表)后的正确结果
Id DateCreated ClientId Result
-- ----------------------- -------- ------
1 2011-03-17 15:52:12.287 66 0
2 2011-03-17 15:52:24.534 68 1
这是使用锁定注释
运行代码的错误结果Id DateCreated ClientId Result
-- ----------------------- -------- ------
1 2011-03-17 15:52:43.128 66 0
2 2011-03-17 15:52:46.341 68 0
有没有更好的方法可以在没有这种黑客的情况下获得交易范围的独占锁?
答案 0 :(得分:7)
我不确定您要发布的代码是做什么的。我假设您只是尝试序列化对该段代码的访问?如果是这样的话sp_getapplock
应该做你需要的,而不是创建一个你只是用来锁定的新的虚拟表。
答案 1 :(得分:1)
您可以在具有可重复读取隔离的事务范围内使用锁定提示WITH(XLOCK,ROWLOCK)。在Serializable隔离时,默认情况下在读操作时获得独占锁,因此如果您需要特定事务并行执行,则可以在创建它时为该一个事务指定增加的序列化级别(您正在执行此操作;这不是不管怎么说,根据具体情况完成任务的方式。