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?
źródło
Odpowiedzi:
Lista
'DDL'
wymienionych operacji nie jest wyczerpująca (iTRUNCATE TABLE
nie jest jedynym pominięciem na tej liście). Czy pytanieTRUNCATE TABLE
jestDML
lubDDL
jest 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-M
blokady , co wyjaśnia blokowanie (ponieważRCSI
iSI
nadal uzyskujeSch-S
blokady ); 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.
źródło