ALLOW_SNAPSHOT_ISOLATION dan READ_COMMITTED_SNAPSHOT

38

Sebagian besar forum dan contoh online selalu menyarankan untuk memiliki keduanya ALLOW_SNAPSHOT_ISOLATIONdan READ_COMMITTED_SNAPSHOTdiatur ke AKTIF setiap kali seseorang meminta snapshot, versi baris atau pertanyaan serupa.

Saya kira kata SNAPSHOT di kedua pengaturan menjadi sedikit membingungkan. Saya berpikir bahwa, agar mesin database menggunakan versi baris alih-alih kunci untuk perilaku default READ_COMMITTED, database READ_COMMITTED_SNAPSHOTdiatur ke ON terlepas dari ALLOW_SNAPSHOT_ISOLATIONpengaturan apa .

The ALLOW_SNAPSHOT_ISOLATIONpengaturan diatur ke ON hanya untuk memungkinkan isolasi snapshot ketika memulai transaksi (misalnya SET TRANSAKSI ISOLASI TINGKAT SNAPSHOT) terlepas dari READ_COMMITTED_SNAPSHOTpengaturan.

Satu-satunya alasan untuk menetapkan kedua pengaturan ini menjadi AKTIF adalah ketika harus memiliki READ COMMITTED versi baris DAN isolasi snapshot.

Pertanyaan saya adalah, apakah pemahaman saya salah dalam beberapa hal? Dan bahwa kedua pengaturan ini harus selalu disetel ke AKTIF bersama (terutama untuk versi baris BACA BERKOMITMEN)?

Travis
sumber

Jawaban:

25

Pemahaman Anda benar. Memang agak membingungkan.

Kim Tripp (salah satu programmer dari SQL Server dan bagian integral dari SQLSkills) melewati apa yang Anda nyatakan dalam video MCM pada Isolasi Snapshot . Cepat temukan di 41:45 dalam video untuk sampai ke bagian di mana dia menjawab pertanyaan Anda.

Jika Anda menggunakan ALLOW_SNAPSHOT_ISOLATIONpastikan Anda menggunakan SET TRANSACTION ISOLATION LEVEL SNAPSHOTkode Anda, jika tidak, Anda tidak akan mendapatkan manfaat apa pun.

Jika Anda mengatur SET READ_COMMITTED_SNAPSHOT ON, maka tidak perlu mengubah kode apa pun. MS SQL Server secara otomatis menerapkan isolasi snapshot untuk tabel itu.

Saya belum menguji untuk melihat apa yang terjadi jika Anda meminta tingkat isolasi yang berbeda dalam kode Anda, saya kira itu akan menimpa opsi ini tetapi mengujinya terlebih dahulu.

Pandangan cepat pada overhead kinerja menggunakan Isolasi Snapshot.

Artikel bagus tentang bagaimana isolasi snapshot dapat mengubah perilaku yang diharapkan dari aplikasi Anda . Ini menunjukkan contoh bagaimana pernyataan pembaruan dan pernyataan pilih dapat mengembalikan hasil yang sama sekali berbeda dan tidak terduga.

Ali Razeghi
sumber
Terima kasih untuk tautannya. Seperti BOL lainnya, dia membahas dua pengaturan ini secara independen dan kolektif (di situlah agak membingungkan, atau mungkin saya terlalu memikirkannya). Saya harus mengujinya untuk mendapatkan pemahaman yang lebih baik.
Travis
4
Ini adalah jawaban yang bagus dan saya hanya ingin mengklarifikasi beberapa item. Pertama, jika Anda hanya memindai video, mulai pukul 23:18 dan 41:45. Waktu awal menambahkan lebih banyak detail. Meskipun Kim menyebutkan jawaban atas pertanyaan awal, masih ada kebutuhan untuk memodifikasi kode jika menggunakan keduanya. Read_Committed_Snapshot adalah isolasi tingkat pernyataan, dengan kata lain hanya berlaku untuk pernyataan yang sedang berjalan. Allow_Snapshot_Isolation adalah isolasi tingkat transaksi, semuanya antara Begin Tran dan Commit. Mereka dapat digunakan secara terpisah, tetapi overhead 14-byte yang sama per baris dibuat.
Delux
terima kasih telah menambahkan detail tambahan pada overhead 14 byte yang sedang dibuat. Kim melewatinya dalam video tetapi sangat berguna untuk memilikinya di sini dalam teks juga.
Ali Razeghi
15

Oke, pulang dan diuji. Inilah pengamatannya.

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

Tes pertama dengan kedua pengaturan dikonfirmasi OFF.

Pertanyaan 1

USE TEST;

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

--COMMIT;
--ROLLBACK;
GO

Pertanyaan 2

USE TEST;

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

Dalam pengujian ini, permintaan 2 sedang menunggu permintaan 1 untuk melakukan, dm_tran_locks DMV menunjukkan bahwa kunci eksklusif pada TABLE1 yang dikeluarkan oleh permintaan 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'

Tes kedua , kembalikan transaksi sebelumnya, setel READ_COMMITTED_SNAPSHOT ON tetapi biarkan ALLOW_SNAPSHOT_ISOLATION OFF.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT ON
WITH ROLLBACK IMMEDIATE;
GO

Jalankan Kueri 1, dan jalankan kueri 2. DMV menampilkan kueri 1 mengeluarkan kunci eksklusif, tetapi kueri 2 mengembalikan detail dengan 'Asli' tanpa kueri 1 melakukan transaksi. Tampaknya READ_COMMITTED versi baris sudah ada.

Menambahkan SET TRANSACTION ISOLATION LEVEL SNAPSHOT;kueri 1 dan kueri 2, dan menjalankan kueri 1 atau kueri 2 mengembalikan kesalahan - Transaksi isolasi snapshot gagal mengakses database 'TEST' karena isolasi snapshot tidak diperbolehkan dalam database ini. Gunakan ALTER DATABASE untuk memungkinkan isolasi snapshot.

Tes ketiga , kembalikan transaksi sebelumnya. Setel OFF READ_COMMITTED_SNAPSHOT dan ALLOW_SNAPSHOT_ISOLATION ON.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT OFF
WITH ROLLBACK IMMEDIATE;
GO

ALTER DATABASE TEST
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

Jalankan kueri 1, lalu kueri 2. DMV memperlihatkan kunci eksklusif yang ditimbulkan oleh kueri 1. Kueri 2 tampaknya menunggu kueri 1 selesai. Menghidupkan ALLOW_SNAPSHOT_ISOLATION ON tampaknya tidak mengaktifkan READ COMMITTED versi baris.

Menambahkan SET TRANSACTION ISOLATION LEVEL SNAPSHOT;ke kueri 1 dan kueri 2. Jalankan kueri 1 dan kemudian kueri 2. Sementara DMV menunjukkan kueri 1 mengeluarkan kunci eksklusif, kueri 2 mengembalikan detail dengan 'Asli'. Isolasi snapshot tampaknya ada di tempatnya.

Pengamatan dari tes menunjukkan bahwa READ_COMMITTED_SNAPSHOTitu sendiri mengaktifkan / menonaktifkan versi baris READ COMMITTED terlepas dari ALLOW_SNAPSHOT_ISOLATIONpengaturan, dan sebaliknya.

Travis
sumber
4

Pemahaman Anda benar. Saya suka definisi singkat, bersih dan sederhana dari sini :

Ketika opsi database READ_COMMITTED_SNAPSHOT adalah AKTIF, transaksi pengaturan tingkat isolasi yang dilakukan baca menggunakan versi baris.

Ketika opsi database ALLOW_SNAPSHOT_ISOLATION adalah AKTIF, transaksi dapat mengatur tingkat isolasi snapshot.

Sepertinya banyak kesalahpahaman berasal dari MS itu sendiri. Sebagai contoh, di sini mereka berkata:

Jika Anda mengatur opsi database READ_COMMITTED_SNAPSHOT ke ON, mesin database menggunakan versi baris dan isolasi snapshot sebagai default, alih-alih menggunakan kunci untuk melindungi data.

Tetapi "isolasi snapshot" yang disebutkan tidak sama dengan perilaku transaksi yang set transaction isolation level snapshotditerapkan.

Adapun perbedaannya, penjelasan yang bagus ada di sini .

Mungkin akan lebih baik jika READ_COMMITTED_SNAPSHOT dinamai sebagai READ_COMMITTED_ROW_VERSIONING atau sesuatu seperti itu. :)

ov
sumber
0

Saya suka ringkasan ini dari Microsoft :

Mengatur opsi READ_COMMITTED_SNAPSHOT ON memungkinkan akses ke baris berversi di bawah tingkat isolasi READ COMMITTED standar. Jika opsi READ_COMMITTED_SNAPSHOT diatur ke OFF, Anda harus secara eksplisit mengatur level isolasi Snapshot untuk setiap sesi untuk mengakses baris berversi.

flam3
sumber