Espero que alguém possa lançar alguma luz sobre esse comportamento que eu não esperava em relação ao isolamento SNAPSHOT vs. TRUNCATE.
Banco de Dados: Permitir Isolamento de Instantâneo = Verdadeiro; Instantâneo de leitura confirmado ativado = falso.
Procedimento1 (Substitui o conteúdo da tabela foo de um SELECT complexo de longa duração com muitas junções):
BEGIN TRAN;
TRUNCATE TABLE foo;
INSERT INTO foo SELECT...;
COMMIT;
Procedimento2 (lê da tabela foo):
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
SELECT * FROM foo;
Se o Procedimento1 estiver em execução enquanto o Procedimento2 for executado, o Procedimento2 será retido com uma espera LCK_M_SCH_S (de acordo com sp_WhoIsActive) até que o Procedimento1 seja concluído. E quando o Procedimento2 é concluído, ele gera esta exceção:
A transação de isolamento de instantâneo falhou no banco de dados 'DatabaseName' porque o objeto acessado pela instrução foi modificado por uma instrução DDL em outra transação simultânea desde o início desta transação. Ele não é permitido porque os metadados não têm controle de versão. Uma atualização simultânea de metadados pode levar à inconsistência se combinada com isolamento de instantâneo.
No entanto, a Microsoft não lista TRUNCATE como uma instrução DDL não permitida sob isolamento SNAPSHOT: http://msdn.microsoft.com/en-us/library/bb933783.aspx
Claramente, não estou entendendo algo corretamente, pois esperava um melhor caso de Procedimento2 retornando imediatamente os dados confirmados mais recentemente da tabela antes do TRUNCATE ou um pior caso de ser retido por Procedimento1 e retornar o novo conteúdo do tabela. Você pode ajudar?
A lista de
'DDL'
operações listadas não é abrangente (eTRUNCATE TABLE
não é a única omissão dessa lista). SeTRUNCATE TABLE
éDML
ouDDL
é uma questão complicada no SQL Server, com exemplos persuasivos em ambos os lados do debate e entradas em ambos os sentidos nos Manuais Online.Do ponto de vista de uma transação de isolamento de instantâneo, o truncate tem a qualidade essencial de obter um
Sch-M
bloqueio , o que explica o bloqueio (porqueRCSI
eSI
ainda adquirirSch-S
bloqueios ); e também altera a versão interna dos metadados (por motivos internos*), resultando no erro 3961.Portanto, o comportamento que você está vendo é esperado, mas não está muito bem documentado.
* A implementação atual de TRUNCATE TABLE não gera versões de linha. Aumentar a versão dos metadados é a maneira mais simples de garantir o comportamento correto.