Espero que alguém possa lançar alguma luz sobre esse comportamento que eu não esperava com relação ao isolamento do INSTANTÂNEO vs. TRUNCATE.
Banco de Dados: Permitir Isolamento de Instantâneo = Verdadeiro; É instantâneo confirmado leitura ativado = falso.
Procedimento1 (Substitui o conteúdo da tabela foo de um SELECT complexo de longa execução por 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á mantido 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, gera esta exceção:
A transação de isolamento de captura instantânea 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. Não é permitido porque os metadados não estão com versão. Uma atualização simultânea de metadados pode levar à inconsistência se combinada com o isolamento de captura instantânea.
No entanto, a Microsoft não lista TRUNCATE como uma instrução DDL não permitida no isolamento do INSTANTÂNEO: http://msdn.microsoft.com/en-us/library/bb933783.aspx
Claramente, não estou entendendo algo corretamente, pois eu esperaria que um melhor caso de Procedure2 retornasse imediatamente os dados confirmados mais recentemente da tabela antes do TRUNCATE ou um pior caso de ser mantido pelo Procedure1 e, em seguida, retornasse o novo conteúdo do tabela. Você pode ajudar?
fonte
Respostas:
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 preocupante em SQL Server, com exemplos convincentes de ambos os lados do debate, e entradas para os dois lados em Books Online.Do ponto de vista de uma transação de isolamento de captura instantânea, truncar tem a qualidade essencial de obter um
Sch-M
bloqueio , o que explica o bloqueio (porqueRCSI
eSI
ainda adquireSch-S
bloqueios ); e também colide com a versão interna de metadados (por motivos internos *), resultando no erro 3961.Portanto, o comportamento que você está vendo é esperado, apenas não muito bem documentado.
* A implementação atual do TRUNCATE TABLE não gera versões de linha. Compartilhar a versão de metadados é a maneira mais simples de garantir o comportamento correto.
fonte