POZIOM IZOLACJI TRANSAKCJI SNAPSHOT vs. TRUNCATE?

10

Mam nadzieję, że ktoś może rzucić nieco światła na to zachowanie, którego nie spodziewałem się w odniesieniu do izolacji SNAPSHOT vs. TRUNCATE.

Baza danych: Allow Snapshot Isolation = True; Czytanie zatwierdzone migawka włączone = fałsz.

Procedura 1 (Zastępuje zawartość tabeli foo z długo działającego kompleksu SELECT dużą ilością sprzężeń):

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

Procedura 2 (czyta z tabeli foo):

SET TRANSACTION ISOLATION LEVEL SNAPSHOT; 
SELECT * FROM foo;

Jeśli Procedura1 jest uruchomiona podczas wykonywania Procedury2, Procedura2 jest wstrzymywana z oczekiwaniem LCK_M_SCH_S (zgodnie z sp_WhoIsActive) do zakończenia Procedury 1. A kiedy Procedura2 zakończy się, pojawia się ten wyjątek:

Transakcja izolacji migawki nie powiodła się w bazie danych „DatabaseName”, ponieważ obiekt, do którego dostęp ma instrukcja, został zmodyfikowany przez instrukcję DDL w innej jednoczesnej transakcji od początku tej transakcji. Jest niedozwolony, ponieważ metadane nie są wersjonowane. Jednoczesna aktualizacja metadanych może prowadzić do niespójności, jeśli zostanie zmieszana z izolacją migawkową.

Jednak Microsoft nie podaje TRUNCATE jako instrukcji DDL niedozwolonej w izolacji SNAPSHOT: http://msdn.microsoft.com/en-us/library/bb933783.aspx

Najwyraźniej nie rozumiem czegoś poprawnie, ponieważ spodziewałbym się, że najlepszy przypadek Procedury 2 natychmiast zwróci ostatnio zatwierdzone dane z tabeli przed TRUNCATE lub najgorszy przypadek zatrzymania przez Procedurę 1, a następnie zwróci nową treść stół. Możesz pomóc?

Mark Freeman
źródło
Czy zamiast tego możesz użyć USUŃ Z Foo? To nie spowoduje blokady schematu.
SqlACID
DELETE FROM to sposób, w jaki pracuję nad tym. Interesuje mnie również, dlaczego pojawia się błąd (i dopiero po powrocie procedury 1).
Mark Freeman

Odpowiedzi:

19

Lista 'DDL'wymienionych operacji nie jest wyczerpująca (i TRUNCATE TABLEnie jest jedynym pominięciem na tej liście). Czy pytanie TRUNCATE TABLEjest DMLlub DDLjest pytaniem trudnym w SQL Server, z przekonującymi przykładami po obu stronach debaty i oboma wpisami w Books Online.

Z punktu widzenia transakcji izolacji migawki, obcinanie ma podstawową jakość przyjmowania Sch-Mblokady , co wyjaśnia blokowanie (ponieważ RCSIi SInadal uzyskuje Sch-Sblokady ); i powoduje także poderwanie wewnętrznej wersji metadanych (z przyczyn wewnętrznych *), co powoduje błąd 3961.

Zatem oczekiwane zachowanie jest po prostu niezbyt dobrze udokumentowane.

* Obecna implementacja TRUNCATE TABLE nie generuje wersji wierszy. Zrzut wersji metadanych to najprostszy sposób na zapewnienie poprawnego zachowania.

Paul White 9
źródło