INSTANTANÉ DE NIVEAU D'ISOLEMENT DE TRANSACTION vs. TRONCATE?

10

J'espère que quelqu'un pourra faire la lumière sur ce comportement auquel je ne m'attendais pas en ce qui concerne l'isolement SNAPSHOT vs TRUNCATE.

Base de données: Autoriser l'isolement de l'instantané = True; Est-ce que l'instantané validé est lu = faux.

Procedure1 (remplace le contenu de la table foo d'un SELECT complexe de longue durée par de nombreuses jointures):

BEGIN TRAN; 
TRUNCATE TABLE foo; 
INSERT INTO foo SELECT...; 
COMMIT;

Procedure2 (lit à partir de la table foo):

SET TRANSACTION ISOLATION LEVEL SNAPSHOT; 
SELECT * FROM foo;

Si Procedure1 est en cours d'exécution pendant l'exécution de Procedure2, Procedure2 est retardé avec une attente LCK_M_SCH_S (selon sp_WhoIsActive) jusqu'à la fin de Procedure1. Et lorsque Procedure2 se termine, il déclenche cette exception:

La transaction d'isolement d'instantané a échoué dans la base de données 'DatabaseName' car l'objet auquel accède l'instruction a été modifié par une instruction DDL dans une autre transaction simultanée depuis le début de cette transaction. Il n'est pas autorisé car les métadonnées ne sont pas versionnées. Une mise à jour simultanée des métadonnées peut entraîner une incohérence si elle est mélangée à l'isolement de l'instantané.

Cependant, Microsoft ne répertorie pas TRUNCATE en tant qu'instruction DDL non autorisée sous l'isolement SNAPSHOT: http://msdn.microsoft.com/en-us/library/bb933783.aspx

De toute évidence, je ne comprends pas quelque chose correctement, car je m'attendais à un meilleur cas de Procedure2 renvoyant immédiatement les données les plus récemment validées de la table avant le TRUNCATE ou au pire des cas de blocage par Procedure1, puis de retour du nouveau contenu du table. Pouvez-vous m'aider?

Mark Freeman
la source
Pouvez-vous utiliser DELETE FROM foo à la place? Cela ne placera pas le verrou de schéma.
SqlACID
EFFACER DE est en effet la façon dont je travaille autour de cela. Je suis également intéressé par la raison pour laquelle j'obtiens l'erreur (et seulement après le retour de Procedure1).
Mark Freeman

Réponses:

19

La liste des 'DDL'opérations répertoriées n'est pas exhaustive (et TRUNCATE TABLEn'est pas la seule omission de cette liste). Que ce TRUNCATE TABLEsoit DMLou DDLest une question difficile dans SQL Server, avec des exemples convaincants des deux côtés du débat et des entrées dans les deux sens dans la documentation en ligne.

Du point de vue d'une transaction d'isolement d'instantané, truncate a la qualité essentielle de prendre un Sch-Mverrou , ce qui explique le blocage (car RCSIet SItoujours acquérir des Sch-Sverrous ); et il heurte également la version interne des métadonnées (pour des raisons internes *) entraînant l'erreur 3961.

Ainsi, le comportement que vous voyez est attendu, mais pas très bien documenté.

* L'implémentation actuelle de TRUNCATE TABLE ne génère pas de versions de ligne. Le remplacement de la version des métadonnées est le moyen le plus simple de garantir un comportement correct.

Paul White 9
la source