Безопасен ли этот запрос в SQL Server? - PullRequest
1 голос
/ 15 апреля 2010

У меня есть запрос на обновление SQL:

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);

Что кажется, возможно, безопаснее, но гораздо медленнее (потому что SELECT будет вызываться в каждой строке таблицы 1 вместо одного выбора для NOT IN)

Ответы [ 2 ]

5 голосов
/ 15 апреля 2010

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

Ваш второй запрос так же небезопасен.

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...