2010-04-14 3 views
1

У меня есть этот SQL запрос обновления:Насколько безопасен этот запрос в SQL Server?

UPDATE table1 
SET table1.field1 = 1 
WHERE table1.id NOT IN (SELECT table2.table1id FROM table2); 

Другие части приложения могут добавлять записи в table2, которые используют поле table1id ссылаться table1.

Целью здесь является удаление записей из таблицы1, на которые не ссылается таблица2.

SQL Server автоматически блокирует таблицу2 с таким типом запроса, чтобы новая запись не могла быть добавлена ​​в таблицу2 при выполнении этого запроса?

Я также рассмотрел:

UPDATE table1 
SET field1 = 1 
WHERE 0 = (SELECT COUNT(*) FROM table2 WHERE table1.id = table2.table1id); 

Который, кажется, возможно, безопаснее, но гораздо медленнее (потому что ВЫБРАТЬ будет называться на каждой строке table1 вместо только один выбор для NOT IN)

+0

Вы используете транзакции? – Nate

+0

Можете ли вы использовать встроенную ссылочную целостность и каскадные удаления? –

+0

Каскадные удаления на самом деле не то, что мне нужно. Целью здесь является только обновление записей в таблице1, на которые не ссылается таблица2. Прежде чем вставить новую запись в таблицу2, она ищет таблицу 1 для соответствующей записи (где также поле1 <> 1), если она находит ее, она затем вставляет новую запись в таблицу2, ссылающуюся на таблицу1. Стол для блокировки2 на самом деле не вариант. – userx

ответ

5

Нет, не является неотъемлемо безопасным. Подзапрос будет захватывать блокировки и немедленно отпустить их, разрешая одновременные обновления/вставки/удаления в таблице2. Также несколько транзакций, выполняющих этот запрос, могут попытаться изменить такие же строки в таблице1, даже если таблица 2 стабильна, что, вероятно, затормозит друг друга.

Ваш второй запрос не менее опасен.

Очень сложно получить эти запросы. Для некоторых запросов вы можете использовать подсказку XLOCK, но в вашем случае вас интересуют недостающие ключи, поэтому это не поможет. Единственный 100% безопасный альтернативный TABLOCKX намек, но это кувалда, который убьет все параллелизм.

В конечном счете вы должны вернуться к чертежу и задать себе бизнес-смысл операции.

  • Что кто-то вставляет ключ в table2 после вы проверили на это? Это не было там, где вы его искали, поэтому ваша операция верна. Если нет, то почему транзакция вставляет что-то другое транзакционное простое удаление? Он восходит к пониманию вашей модели домена для принятия правильного решения.
  • Что вы блокируете вставку нового ключа в таблице2 при обновлении таблицы1? Чем это отличается от вышеприведенного?
  • Что-то удаляет ключ, который вы нашли в таблице2 после ваш запрос не обновил таблицу1, потому что ключ присутствовал? Как и раньше, как это отличается от удаления ключа после завершения обновления?
0

Нет, не будет. Блоки будут выпущены, как только они смогут. Записи в таблице 2 будут временно заблокированы, так что вы получите записи в течение некоторого момента времени и на основе этого момента ваши записи будут удалены из таблицы 1.

Я думаю, что ваша цель состоит в том, чтобы вы вставляли записи в таблицу2 перед таблицей1.