Я надеюсь, что кто-то может пролить некоторый свет на это поведение, которого я не ожидал в отношении изоляции SNAPSHOT против TRUNCATE.
База данных: Разрешить изоляцию моментального снимка = True; Считано, зафиксированный снимок включен = False.
Процедура 1 (заменяет содержимое таблицы foo из долго выполняющегося комплекса SELECT множеством объединений):
BEGIN TRAN;
TRUNCATE TABLE foo;
INSERT INTO foo SELECT...;
COMMIT;
Процедура2 (читает из таблицы foo):
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
SELECT * FROM foo;
Если Процедура1 выполняется во время выполнения Процедуры2, Процедура2 задерживается с ожиданием LCK_M_SCH_S (согласно sp_WhoIsActive) до завершения Процедуры1. И когда процедура2 завершается, возникает это исключение:
Не удалось выполнить транзакцию изоляции моментального снимка в базе данных «DatabaseName», поскольку объект, к которому обращается оператор, был изменен оператором DDL в другой параллельной транзакции с момента начала этой транзакции. Это запрещено, поскольку метаданные не являются версионными. Одновременное обновление метаданных может привести к несогласованности при смешивании с изоляцией моментального снимка.
Однако Microsoft не перечисляет TRUNCATE как оператор DDL, не разрешенный в изоляции SNAPSHOT: http://msdn.microsoft.com/en-us/library/bb933783.aspx
Понятно, что я что-то не правильно понимаю, так как я ожидал, что лучший вариант процедуры2 немедленно возвращает самые последние зафиксированные данные из таблицы перед TRUNCATE или наихудший случай задержки процедурой1 и затем возвращается новое содержимое стол. Вы можете помочь?
источник
Ответы:
Список
'DDL'
перечисленных операций не является исчерпывающим (иTRUNCATE TABLE
не является единственным упущением в этом списке). Является лиTRUNCATE TABLE
этоDML
или нетDDL
чересчур сложным вопросом в SQL Server, с убедительными примерами по обе стороны дискуссии и с записями в обе стороны в Books Online.С точки зрения транзакции изоляции моментального снимка, truncate обладает необходимым качеством взятия
Sch-M
блокировки , которая объясняет блокировку (потому чтоRCSI
иSI
все еще получаетSch-S
блокировки ); и это также изменяет внутреннюю версию метаданных (по внутренним причинам *), что приводит к ошибке 3961.Итак, поведение, которое вы видите, ожидается, но не очень хорошо задокументировано.
* Текущая реализация TRUNCATE TABLE не генерирует версии строк. Изменение версии метаданных - это самый простой способ обеспечить правильное поведение.
источник