【发布时间】:2010-09-10 09:42:12
【问题描述】:
我在存储过程中使用 UPDLOCK 和 READPAST sql 提示来实现一种表队列(我说排序是因为我选择了前 1500 个而不是前 1 个,并且我没有删除我选择它们后的行。有关更多详细信息,请参阅问题Return unlocked rows in a "select top n" query)。
我用一个简单的小表进行了一些测试,一切似乎都很好 - SP 的第二次调用不等待第一次调用结束,只是跳过第一次调用锁定的行,并返回下一个。不过,在我的真实桌子上,它有时只能工作......其他时候,第二个电话挂起并等待第一个电话结束。这是因为第一次调用会锁定整个表,而不仅仅是一些行。
这些是测试表和真实表的 SP:
实桌:
declare @temp as table (ID int primary key, timestamp datetime)
BEGIN TRANSACTION
insert into @temp
SELECT TOP 1 ID, getdate()
FROM subscription WITH (UPDLOCK, READPAST)
WHERE IsBeingProcessed = 0
waitfor delay '00:00:10'
UPDATE subscription
SET IsBeingProcessed = 1
from subscription
inner join @temp t on subscription.id = t.id
COMMIT TRANSACTION
select * from @temp t
inner join subscription s on s.id = t.id
测试表:
declare @temp as table (ID int primary key)
BEGIN TRANSACTION
insert into @temp(id)
select top 1 id
from test WITH (UPDLOCK, READPAST)
where msg like 'test'
waitfor delay '00:00:10'
UPDATE test
SET timestamp = getdate()
from test
inner join @temp t1 on test.id = t1.id
COMMIT TRANSACTION
select * from test t
inner join @temp t1 on t.id = t1.id
运行 sp_lock 我看到第一个 SP 在我的整个“真实”表上持有一个独占表锁,而第二个 SP 使用意图独占锁等待。对于我的“测试”表,我在索引和行 ID 上有一个更新锁,在两页上有两个意图更新锁,在整个表上有一个意图排他锁。
您是否知道什么可能导致“真实表”的整个表锁定?
也许我在那个表上有一些聚集索引,也许我缺少一些索引?我不知道。
我发布的示例非常简单——它有一个“前 1”,没有“排序依据”。我真正的选择将有一个“按 id 排序”和“前 1500 名”,可能是“前 3000 名”。这可能会使锁定问题更加严重。
非常欢迎任何想法!谢谢。
【问题讨论】:
-
您使用的是什么版本的 SQL Server?
-
没有
ORDER BY时,top 1是什么意思?想想这个问题及其对您的索引的影响。请记住,真正的队列是先进先出的。队列查询中最具选择性的条件是 order by + top 组合。
标签: sql-server sql-server-2005 tsql concurrency