ALLOW_SNAPSHOT_ISOLATION i READ_COMMITTED_SNAPSHOT

38

Większość forum i przykładów online zawsze sugeruje, aby mieć oba te elementy ALLOW_SNAPSHOT_ISOLATIONi READ_COMMITTED_SNAPSHOTustawić je na WŁĄCZONE, gdy ktoś zadaje migawkę, wersję wiersza lub podobne pytanie.

Wydaje mi się, że słowo SNAPSHOT w obu ustawieniach jest trochę mylące. Pomyślałem, że aby silnik bazy danych używał wersjonowania wierszy zamiast blokad dla domyślnego zachowania READ_COMMITTED, baza danych READ_COMMITTED_SNAPSHOTjest ustawiona na ON bez względu na to, jakie ALLOW_SNAPSHOT_ISOLATIONustawienie.

ALLOW_SNAPSHOT_ISOLATIONJest ustawiona na ON wyłącznie w celu umożliwienia izolacji migawka podczas uruchamiania transakcji (np TRANSAKCJI izolacji migawka LEVEL SET) niezależnie od READ_COMMITTED_SNAPSHOTustawienia.

Jedynym powodem, dla którego te dwa ustawienia są ustawione na WŁĄCZONE, jest konieczność odczytania wersji wiersza ORAZ izolacji migawek.

Moje pytanie brzmi: czy moje rozumowanie jest w jakiś sposób nieprawidłowe? I że te dwa ustawienia muszą być zawsze ustawione razem na WŁĄCZONE (szczególnie w przypadku READ COMMITTED wersji wiersza)?

Travis
źródło

Odpowiedzi:

25

Twoje zrozumienie jest prawidłowe. To robi się trochę mylące.

Kim Tripp (jeden z programistów SQL Server i integralna część SQLSkills) dokładnie omawia to, co napisałeś w filmach MCM na temat Snapshot Isolation . Szybki film do 41:45 w filmie, aby przejść do części, w której odpowiada na twoje pytanie.

Jeśli używasz, ALLOW_SNAPSHOT_ISOLATIONupewnij się, że używasz SET TRANSACTION ISOLATION LEVEL SNAPSHOTkodu, w przeciwnym razie nie uzyskasz żadnych korzyści.

Jeśli ustawisz SET READ_COMMITTED_SNAPSHOT ON, nie musisz modyfikować żadnego kodu. MS SQL Server automatycznie stosuje izolację migawek dla tej tabeli.

Nie testowałem, aby zobaczyć, co się stanie, jeśli poprosisz o inny poziom izolacji w kodzie. Podejrzewam, że zastąpi tę opcję, ale najpierw ją przetestuj.

Szybkie spojrzenie na narzut wydajności przy użyciu Snapshot Isolation.

Dobry artykuł o tym, jak izolacja migawek może zmienić oczekiwane zachowanie aplikacji . Pokazuje przykłady, w jaki sposób instrukcja aktualizacji i instrukcja select mogą zwracać zupełnie inne i nieoczekiwane wyniki.

Ali Razeghi
źródło
Dzięki za link. Podobnie jak inne BOL, omawiała te dwa ustawienia niezależnie i zbiorowo (w tym miejscu robi się to trochę mylące, a może nawet to uważam). Musiałem to przetestować, aby uzyskać lepsze zrozumienie.
Travis,
4
To świetna odpowiedź i chciałbym jedynie wyjaśnić kilka kwestii. Po pierwsze, jeśli tylko skanujesz wideo, zacznij od 23:18 i 41:45. Wczesny czas dodaje więcej szczegółów. Chociaż Kim wspomina odpowiedź na pierwotne pytanie, nadal istnieje potrzeba modyfikacji kodu, jeśli używasz obu. Read_Committed_Snapshot to izolacja na poziomie instrukcji, innymi słowy dotyczy tylko aktualnie uruchomionej instrukcji. Allow_Snapshot_Isolation to izolacja na poziomie transakcji, wszystko między Begin Tran a Commit. Można je włączyć osobno, ale ustanawia się taki sam narzut 14 bajtów na wiersz.
Delux,
dziękuję za dodanie dodatkowych szczegółów dotyczących ustanawiania narzutu 14-bajtowego. Kim przechodzi przez to w filmie, ale bardzo przydatne jest, aby mieć go również w tekście.
Ali Razeghi,
15

OK, wróciłem do domu i przetestowałem. Oto obserwacja.

CREATE DATABASE TEST;
GO
CREATE TABLE TABLE1
(
    ID tinyint,
    Details varchar(10)
);
GO
INSERT INTO TABLE1
VALUES (1, 'Original');
GO

SELECT
    name,
    snapshot_isolation_state_desc,
    is_read_committed_snapshot_on
FROM sys.databases
WHERE name = 'TEST';
GO

Pierwszy test z obydwoma ustawieniami potwierdzonymi jako WYŁ.

Zapytanie 1

USE TEST;

BEGIN TRAN
UPDATE TABLE1
SET Details = 'Update'
WHERE ID = 1;

--COMMIT;
--ROLLBACK;
GO

Zapytanie 2

USE TEST;

SELECT ID, Details
FROM TABLE1
WHERE ID = 1;
GO

W tym teście zapytanie 2 oczekuje na zatwierdzenie zapytania 1, dm_tran_locks DMV pokazuje, że blokada wyłączności na TABELI 1 została wywołana przez zapytanie 1.

USE TEST;

SELECT
    DB_NAME(tl.resource_database_id) AS DBName,
    resource_type,
    OBJECT_NAME(resource_associated_entity_id) AS tbl_name,
    request_mode,
    request_status,
    request_session_id
FROM sys.dm_tran_locks tl
WHERE 
    resource_database_id = db_id('TEST')
    AND resource_type = 'OBJECT'

Drugi test , wycofaj poprzednią transakcję, ustaw READ_COMMITTED_SNAPSHOT na ON, ale pozostaw ALLOW_SNAPSHOT_ISOLATION na OFF.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT ON
WITH ROLLBACK IMMEDIATE;
GO

Uruchom zapytanie 1 i zapytanie 2. DMV pokazuje, że zapytanie 1 otrzymuje wyłączną blokadę, ale zapytanie 2 zwraca szczegóły z „Oryginalnym” bez zapytania 1 zatwierdzenia transakcji. Wygląda na to, że istnieje wersja READ_COMMITTED.

Dodanie SET TRANSACTION ISOLATION LEVEL SNAPSHOT;do zapytania 1 i zapytania 2 oraz uruchomienie zapytania 1 lub zapytania 2 zwraca błąd - Transakcja izolacji migawki nie powiodła się podczas uzyskiwania dostępu do bazy danych „TEST”, ponieważ izolacja migawki nie jest dozwolona w tej bazie danych. Użyj ALTER DATABASE, aby umożliwić izolację migawki.

Trzeci test , wycofaj poprzednią transakcję. Ustaw READ_COMMITTED_SNAPSHOT w pozycji OFF i ALLOW_SNAPSHOT_ISOLATION w pozycji ON.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT OFF
WITH ROLLBACK IMMEDIATE;
GO

ALTER DATABASE TEST
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

Uruchom zapytanie 1, a następnie zapytanie 2. DMV pokazuje wyłączną blokadę wywołaną przez zapytanie 1. Wydaje się, że zapytanie 2 oczekuje na zakończenie zapytania 1. Włączenie opcji ALLOW_SNAPSHOT_ISOLATION ON nie wydaje się włączać wersji dla READ COMMITTED.

Dodawanie SET TRANSACTION ISOLATION LEVEL SNAPSHOT;zarówno do zapytania 1, jak i zapytania 2. Uruchom zapytanie 1, a następnie zapytanie 2. Podczas gdy DMV pokazuje, że zapytanie 1 ma wyłączną blokadę, zapytanie 2 zwraca szczegóły za pomocą „Oryginału”. Wydaje się, że izolacja migawki jest na miejscu.

Obserwacja z testu pokazuje, że READ_COMMITTED_SNAPSHOTsamo włącza / wyłącza READ COMMITTED wersjonowanie wierszy, niezależnie od ALLOW_SNAPSHOT_ISOLATIONustawienia, i odwrotnie.

Travis
źródło
4

Twoje zrozumienie jest prawidłowe. Podoba mi się krótka, czysta i prosta definicja stąd :

Gdy opcja bazy danych READ_COMMITTED_SNAPSHOT jest WŁĄCZONA, transakcje ustawiające odczytany zatwierdzony poziom izolacji używają wersji wiersza.

Gdy opcja bazy danych ALLOW_SNAPSHOT_ISOLATION jest WŁĄCZONA, transakcje mogą ustawić poziom izolacji migawki.

Wydaje się, że wiele nieporozumień pochodzi od samego SM. Na przykład tutaj mówią:

Jeśli ustawisz opcję bazy danych READ_COMMITTED_SNAPSHOT na WŁ., Aparat bazy danych używa domyślnie wersjonowania wierszy i izolacji migawek zamiast blokad w celu ochrony danych.

Ale wspomniana „izolacja migawki” nie jest równa zachowaniu transakcji, dla której set transaction isolation level snapshotjest stosowana.

Jeśli chodzi o różnicę, ładne wyjaśnienie jest tutaj .

Prawdopodobnie byłoby lepiej, gdyby READ_COMMITTED_SNAPSHOT został nazwany READ_COMMITTED_ROW_VERSIONING lub coś w tym rodzaju. :)

ov
źródło
0

Podoba mi się to podsumowanie od Microsoft :

Ustawienie opcji READ_COMMITTED_SNAPSHOT ON umożliwia dostęp do wersjonowanych wierszy na domyślnym poziomie izolacji READ COMMITTED. Jeśli opcja READ_COMMITTED_SNAPSHOT jest ustawiona na OFF, musisz jawnie ustawić poziom izolacji migawki dla każdej sesji, aby uzyskać dostęp do wersjonowanych wierszy.

flam3
źródło