Как сделать блокировку в SQL Server, как MYSQL - PullRequest
0 голосов
/ 04 января 2010

Я конвертирую веб-приложение из mysql в SQL Server. Теперь я хочу преобразовать следующий код (это упрощенная версия):

LOCK TABLES media WRITE, deleted WRITE;
INSERT INTO deleted (stuff) SELECT stuff FROM media WHERE id=1 OR id=2;
DELETE FROM media WHERE id=1 OR id=2;
UNLOCK TABLES;

Поскольку я копирую материал, который будет удален, я хочу убедиться, что все операции чтения на «носителе» или «удаленные» будут ждать, пока вся эта операция не будет готова. В противном случае эти операции чтения увидят то, чего больше нет ни секунды спустя.

Как я могу повторить это поведение в SQL Server? Я читаю некоторые страницы о транзакциях и уровнях изоляции, но не могу понять, могу ли я отключить какие-либо операции чтения в таблицу «media» и «delete» (или на уровне строк).

Thanx!

Ответы [ 2 ]

1 голос
/ 04 января 2010

Вы можете использовать подсказки блокировки в вашем запросе. Если указать блокировку таблицы и удерживать ее до конца транзакции, это должно быть эквивалентно.

begin transaction;

INSERT INTO deleted
   SELECT stuff FROM media WITH (tablock holdlock)
   WHERE id = 1 or id = 2;

DELETE FROM media where id = 1 or id = 2;

commit;
0 голосов
/ 04 января 2010

В качестве подхода, не зависящего от БД, вы можете рассмотреть возможность использования столбца «удаленный» или «неактивный», указывающего, следует ли возвращать результаты пользователям. Например, вы можете использовать целое число для столбца, исключая запись из поля зрения пользователя, если значение столбца не равно нулю. Таким образом, вместо выбора и вставки выше, вы можете сделать (все примеры на диалекте MySQL SQL):

UPDATE media SET inactive=1 WHERE stuff=1 OR stuff=2;

Это исключит записи из представления пользователя. Затем вы можете скопировать неактивные записи в «удаленную» таблицу и при желании удалить их из таблицы мультимедиа в зависимости от времени последнего обновления неактивных записей:

INSERT INTO deleted (stuff) SELECT stuff FROM media WHERE inactive = 1;
DELETE from media WHERE inactive <= 1;

Целое число может использоваться для идентификации "неактивного задания", которое "удаляет" записи.

Исходя из того, как вы описали схему, этот сценарий не совсем соответствует подходу блокировки, поскольку таблица «media» может быть изменена во время выполнения оператора UPDATE. Эту проблему можно решить (или, по крайней мере, смягчить), если бы существовал столбец, такой как отметка времени, который можно было бы использовать для дальнейшего определения записей для пометки неактивных.

...