У меня есть вопрос о том, почему некоторые SQL (работающие на SQL Server 2005) ведут себя так, как есть. В частности, я внес изменения, чтобы уменьшить конфликт блокировок во время обновления, и, похоже, он работает в тех случаях, когда я не думал, что это будет.
Оригинальный код:
У нас был такой оператор обновления, который применялся к таблице с более чем 3 000 000 записей:
UPDATE USER WITH (ROWLOCK)
SET Foo = 'N', Bar = getDate()
WHERE ISNULL(email, '') = ''
AND Foo = 'Y'
Как вы, наверное, догадались, это на какое-то время заблокировало таблицу USER. Даже с подсказкой ROWLOCK другие задания, выполняющие запросы и обновления для пользователя USER, будут блокироваться, пока это не будет сделано. Это неприемлемо для данного конкретного приложения, поэтому я решил применить хитрость, о которой читал, когда оператор update обновляет только 100 записей за раз. Это дало бы возможность другим запросам время от времени попадать за стол.
Улучшенный код:
DECLARE @LOOPAGAIN AS BIT;
SET @LOOPAGAIN = 1;
WHILE @LOOPAGAIN = 1
BEGIN
UPDATE TOP (100) USER WITH (ROWLOCK)
SET Foo = 'N', Bar = getDate()
WHERE ISNULL(email, '') = ''
AND Foo = 'Y'
IF @@ROWCOUNT > 0
SET @LOOPAGAIN = 1
ELSE
SET @LOOPAGAIN = 0
END
Это добилось цели. Наше обновление сработало, и другие запросы смогли попасть за стол. Все есть счастье и свет.
Тайна:
Я понимаю, как это улучшило производительность, когда в таблице было много записей, которые нужно было обновить. Быстро пройдя через цикл после каждых 100 обновлений, он дал другим запросам шанс попасть за стол. Тайна в том, что этот цикл имел тот же эффект, даже когда обновление не затронуло ни одной записи!
Во второй раз, когда мы выполняем наш исходный запрос, он будет выполняться только часть времени (скажем, 30 секунд или около того), но он заблокирует таблицу в течение этого времени, даже если никакие записи не изменялись. Но поместите запрос в цикл с предложением «TOP (100)», и, хотя для того, чтобы ничего не делать, потребовалось столько же времени, он освободил таблицу для других запросов!
Я очень удивлен этим. Может кто-нибудь сказать мне:
- Если то, что я только что сказал, совершенно ясно и,
- Почему второй блок кода позволяет другим запросам попасть в таблицу, даже если записи не обновляются?