Как IDENTITY_INSERT влияет на параллелизм?


11

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

При определенных обстоятельствах он архивирует и неполное сообщение из таблицы очередей публикации в таблицу архивации сообщений. Мне нужно переместить эти архивные результаты обратно в очередь.

Идентификатор очереди - это столбец идентификаторов, и я хотел бы оставить его таким же.

Вопрос в том, что если я выполню identity_insert в / insert / identity_insert off, что я могу ожидать в отношении параллелизма с процессами, которые создают записи в очереди и ожидают, что столбец идентификаторов будет сгенерирован автоматически?

Любые указатели на лучший способ продемонстрировать такое поведение также будут высоко оценены.

Ответы:


8

Установка IDENTITY_INSERT ONсама по себе не устраняет параллелизм - это не создает никаких исключительных блокировок на столе, только блокировку краткой стабильности схемы (Sch-S).

Итак, что теоретически может произойти при поведении по умолчанию, вы можете сделать это в сеансе 1:

BEGIN TRANSACTION;

-- 1
SET IDENTITY_INSERT dbo.tablename ON;

-- 2
INSERT dbo.tablename(id, etc) VALUES(100, 'foo'); -- next identity is now 101

-- 3
INSERT dbo.tablename(id, etc) VALUES(101, 'foo'); -- next identity is now 102

-- 4
SET IDENTITY_INSERT dbo.tablename OFF;

COMMIT TRANSACTION;

В другом сеансе вы можете вставить строки в таблицу в точках 1, 2, 3 или 4. Это может показаться хорошим вариантом, за исключением того, что происходит для любой вставки, которая происходит между 2 и 3, это то, что автоматически сгенерированное значение срабатывает другой сеанс основан на результатах оператора 2 - поэтому он сгенерирует 101, а затем оператор 3 потерпит неудачу с нарушением первичного ключа. Это довольно просто настроить и проверить себя с некоторыми WAITFORs:

-- session 1
-- DROP TABLE dbo.what;
CREATE TABLE dbo.what(id INT IDENTITY PRIMARY KEY);
GO
BEGIN TRANSACTION;

SET IDENTITY_INSERT dbo.what ON;

INSERT dbo.what(id) VALUES(32);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(33);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(34);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(35);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(36);

SET IDENTITY_INSERT dbo.what OFF;

COMMIT TRANSACTION;

Как только этот пакет запущен, запустите этот пакет в другом окне:

-- session 2
INSERT dbo.what DEFAULT VALUES;
WAITFOR DELAY '00:00:01';
GO 20

Сессия 2 должна только когда-либо вставлять значения от 1 до 20, верно? За исключением того, что из-за того, что базовая идентификационная информация была обновлена ​​вашим сеансом 1 вставки вручную, в какой-то момент сеанс 2 выберет, где сеанс 1 закончился, и вставит 32, или 33, или 34 и т. Д. Это будет разрешено сделать, но затем сеанс 1 завершится неудачно при следующей вставке с нарушением PK (выигрыш которого может быть просто вопросом времени).

Один из способов обойти это - вызвать a TABLOCKпри первой вставке:

INSERT dbo.what WITH (TABLOCK) (id) VALUES(32);

Это заблокирует любых других пользователей, пытающихся вставить (или сделать что-нибудь на самом деле) с этой таблицей, пока вы не закончите перемещение этих заархивированных строк назад. Конечно, это ограничивает параллелизм, но именно так вы хотите, чтобы блокировка работала. И, надеюсь, это не то, что происходит так часто, когда вы все время блокируете других людей.

Пара других обходных путей:

  • прекратить заботиться о IDENTITYсгенерированной стоимости. Какая разница? Используйте UNIQUEIDENTIFIER(может быть сгенерировано в отдельной таблице с IDENTITYсуррогатом), если исходное значение очень важно.
  • измените процесс архивирования, чтобы использовать «мягкое удаление», когда что-то помечается как изначально заархивированное, а архивирование не становится постоянным до более поздней даты. Тогда любой процесс, который пытается переместить их обратно, может просто выполнить прямое обновление и установить флаг мягкого удаления.

Спасибо за ваше объяснение. Я пишу отдельную утилиту, чтобы помочь с продуктом без поддержки, который создает эти поля идентификации. Я не контролирую, как это работает.
Метафора
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.