У меня возникает вопрос, почему какой-то SQL (работает на SQL Server 2005) ведет себя так, как есть. В частности, я сделал изменения, чтобы уменьшить конфликт блокировок во время обновления, и, похоже, он работает в тех случаях, когда я не думал, что это произойдет.Почему SQL Update Top, по-видимому, снижает блокировку, даже когда никакие записи не обновляются?
Оригинальный код:
У нас было обновление заявление, как это, что в настоящее время применяется к таблице с более чем 3000000 записей:
UPDATE USER WITH (ROWLOCK)
SET Foo = 'N', Bar = getDate()
WHERE ISNULL(email, '') = ''
AND Foo = 'Y'
Как вы можете догадаться, это, казалось, временно заблокируйте таблицу USER. Даже с подсказкой ROWLOCK другие задания, выполняющие запросы и обновления против USER, блокируются до тех пор, пока это не будет выполнено. Это неприемлемо для этого конкретного приложения, поэтому я подумал, что применил бы трюк, о котором я читал, если инструкция обновления обновляет только 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)», и хотя потребовалось столько же времени, чтобы ничего не делать, он высвободил таблицу для других запросов!
Я очень удивлен этим. Может кто-нибудь сказать мне:
- Если то, что я только что сказал, совсем ясно, и,
- Почему второй блок кода позволяет другие запросы, чтобы получить за столом, даже если нет записей обновляемые?
Я считаю, что он все еще должен «ВЫБРАТЬ» перед таблицей, прежде чем он осознает, что для обновления нет строк. – 2009-11-10 20:32:43
На каком уровне изоляции транзакций? –