【发布时间】:2016-03-21 16:04:58
【问题描述】:
已编辑:我有一个包含复合键的表,它被部署在多个服务器上的多个 Windows 服务使用。
列:
UserId (int) [CompositeKey],
CheckinTimestamp (bigint) [CompositeKey],
Status (tinyint)
此表中会不断插入。我希望我的 Windows 服务选择前 10000 行并进行一些处理,同时仅锁定这 10000 行。我正在使用以下存储过程为此使用 ROWLOCK:
ALTER PROCEDURE LockMonitoringSession
AS
BEGIN
BEGIN TRANSACTION
SELECT TOP 10000 * INTO #TempMonitoringSession FROM dbo.MonitoringSession WITH (ROWLOCK) WHERE [Status] = 0 ORDER BY UserId
DECLARE @UserId INT
DECLARE @CheckinTimestamp BIGINT
DECLARE SessionCursor CURSOR FOR SELECT UserId, CheckinTimestamp FROM #TempMonitoringSession
OPEN SessionCursor
FETCH NEXT FROM SessionCursor INTO @UserId, @CheckinTimestamp
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE dbo.MonitoringSession SET [Status] = 1 WHERE UserId = @UserId AND CheckinTimestamp = @CheckinTimestamp
FETCH NEXT FROM SessionCursor INTO @UserId, @CheckinTimestamp
END
CLOSE SessionCursor
DEALLOCATE SessionCursor
SELECT * FROM #TempMonitoringSession
DROP TABLE #TempMonitoringSession
COMMIT TRANSACTION
END
但是这样做,dbo.MonitoringSession 将被永久锁定,直到存储过程结束。我不确定我在这里做错了什么。
此存储过程的唯一目的是选择和更新 10000 条最近没有任何主键的行,并确保整个表不会因为多个 Windows 服务正在访问此表而被锁定。
提前感谢您的帮助。
【问题讨论】:
-
top没有order by,update中没有where- 这只是在带有问题的简化代码中发布?你能发布select-top的实际执行计划吗? -
如果你只是更新 10 行,为什么还需要一个循环呢?这可以在一个语句中完成。
-
你的
UPDATE语句没有WHERE子句,所以这个UPDATE操作应用于对整个表,所以表中的每一行都是完全锁定以执行UPDATE..... -
按照马克所说的,你正在执行相同的操作 50 K 次
-
伙计们,我已经编辑了问题并发布了原始代码。我还改写了这个问题,并提到了这个 SP 的目的。请现在看看。谢谢。
标签: sql-server stored-procedures