LIVELLO DI ISOLAMENTO DELL'OPERAZIONE SNAPSHOT vs. TRUNCATE?


10

Spero che qualcuno possa far luce su questo comportamento che non mi aspettavo per quanto riguarda l'isolamento SNAPSHOT rispetto a TRUNCATE.

Database: consenti isolamento snapshot = True; È stato letto l'istantanea confermata attivata = Falso.

Procedura 1 (Sostituisce il contenuto della tabella foo da un complesso SELECT di lunga durata con molti join):

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

Procedura2 (Legge dalla tabella foo):

SET TRANSACTION ISOLATION LEVEL SNAPSHOT; 
SELECT * FROM foo;

Se la Procedura1 è in esecuzione mentre la Procedura2 viene eseguita, la Procedura2 viene trattenuta con un'attesa LCK_M_SCH_S (secondo sp_WhoIsActive) fino al completamento della Procedura1. E quando la procedura2 viene completata, genera questa eccezione:

Transazione di isolamento dello snapshot non riuscita nel database 'DatabaseName' perché l'oggetto a cui accede l'istruzione è stato modificato da un'istruzione DDL in un'altra transazione simultanea dall'inizio di questa transazione. Non è consentito perché i metadati non sono sottoposti a versione. Un aggiornamento simultaneo dei metadati può causare incoerenze se mescolato con l'isolamento dello snapshot.

Tuttavia, Microsoft non elenca TRUNCATE come un'istruzione DDL non consentita dall'isolamento SNAPSHOT: http://msdn.microsoft.com/en-us/library/bb933783.aspx

Chiaramente non sto capendo qualcosa correttamente, poiché mi sarei aspettato un caso migliore di Procedura2 che restituisse immediatamente i dati più recenti impegnati dalla tabella prima del TRUNCATE o un caso peggiore di essere trattenuto da Procedura1 e quindi restituendo il nuovo contenuto del tavolo. Puoi aiutare?


Puoi usare DELETE FROM foo invece? Ciò non posizionerà il blocco dello schema.
SqlACID,

DELETE FROM è davvero il modo in cui sto lavorando intorno a questo. Sono anche interessato al motivo per cui sto ricevendo l'errore (e solo dopo che la Procedura1 ritorna).
Mark Freeman,

Risposte:


19

L'elenco delle 'DDL'operazioni elencate non è completo (e TRUNCATE TABLEnon è l'unica omissione da tale elenco). Se TRUNCATE TABLEè DMLo DDLè una domanda difficile in SQL Server, con esempi persuasivi su entrambi i lati del dibattito e voci in entrambi i modi nella documentazione online.

Dal punto di vista di una transazione di isolamento di un'istantanea, troncare ha la qualità essenziale di prendere un Sch-Mblocco , il che spiega il blocco (perché RCSIe SIancora acquisire i Sch-Sblocchi ); e blocca anche la versione interna dei metadati (per motivi interni *) con conseguente errore 3961.

Quindi, il comportamento che stai vedendo è previsto, ma non documentato molto bene.

* L'attuale implementazione di TRUNCATE TABLE non genera versioni di riga. Saltare la versione dei metadati è il modo più semplice per garantire un comportamento corretto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.