ALLOW_SNAPSHOT_ISOLATION ve READ_COMMITTED_SNAPSHOT


38

Forum ve çevrimiçi örneklerin çoğu, her zaman birisinin anlık görüntü, satır sürümü veya benzer bir soru sorması durumunda her ikisine de sahip olmayı ALLOW_SNAPSHOT_ISOLATIONve READ_COMMITTED_SNAPSHOTAÇIK olarak ayarlanmasını önerir .

Sanırım her iki ayardaki SNAPSHOT kelimesi biraz kafa karıştırıcı oluyor. Veritabanı motorunun, READ_COMMITTED varsayılan davranışı için kilit yerine satır sürümü kullanabilmesi için , hangi ayardan bağımsız olarak veritabanının READ_COMMITTED_SNAPSHOTAÇIK olarak ayarlandığını düşündüm .ALLOW_SNAPSHOT_ISOLATION

ALLOW_SNAPSHOT_ISOLATIONAyar bir işlem (örneğin SET HAREKET YALıTıM DÜZEYINE SNAPSHOT) başlatırken sadece anlık yalıtım izin ON olarak ayarlandığında bakılmaksızın ait READ_COMMITTED_SNAPSHOTayarına.

Bu iki ayarın ON (AÇIK) olarak ayarlanması için tek neden, OKUMA KOMİTESİ satır versiyonlaması VE anlık görüntü yalıtımının olması gerektiği zamandır .

Sorum şu, anlayışım bir şekilde yanlış mı? Ve bu iki ayarın hep birlikte AÇIK olarak ayarlanması gerekir (özellikle READ COMMITTED satır versiyonları için)?

Yanıtlar:


25

Anlayışınız doğru. Biraz kafa karıştırıcı olur.

Kim Tripp (SQL Server programcılarından biri ve SQLSkills'in ayrılmaz bir parçası) Snapshot Isolation ile ilgili MCM videolarında tam olarak söylediklerinizden geçiyor . Videoda 41: 45'e hızlı bir şekilde cevap verin ve sorunuzu yanıtladığı bölüme gidin.

Kullanırsanız , kodunuzda ALLOW_SNAPSHOT_ISOLATIONkullandığınızdan emin olun SET TRANSACTION ISOLATION LEVEL SNAPSHOT, aksi takdirde, hiçbir avantaj elde edemezsiniz.

Ayarladıysanız SET READ_COMMITTED_SNAPSHOT ON, herhangi bir kodu değiştirmenize gerek yoktur. MS SQL Server bu tablo için otomatik olarak anlık görüntü yalıtımını uygular.

Kodunuzda farklı bir yalıtım düzeyi istemeniz durumunda ne olacağını test etmedim, bu seçeneğin üzerine yazacağından şüpheleniyorum, ancak önce sınayın.

Anlık Görüntü İzolasyonu kullanarak performans ek yüküne hızlı bir bakış.

Anlık görüntü yalıtımının uygulamanızın beklenen davranışını nasıl değiştirebileceği hakkında iyi bir makale . Bir güncelleme ifadesinin ve bir seçim ifadesinin tamamen farklı ve beklenmedik sonuçlara nasıl dönebileceğinin örneklerini gösterir.


Bağlantı için teşekkürler. Diğer BOL gibi, bu iki ortamı bağımsız olarak ve toplu olarak tartıştı (biraz kafa karıştırıcı olduğu veya belki de üzerinde düşündüğüm yer). Daha iyi bir anlayış elde etmek için denemek zorundaydım.
Travis,

4
Bu harika bir cevap ve sadece birkaç maddeyi açıklığa kavuşturmak istiyorum. İlk önce, videoyu tarıyorsanız, 23:18 ve 41:45 ile başlayın. Erken zaman daha fazla ayrıntı ekler. Kim asıl sorunun cevabından bahsetmekle birlikte, her ikisini de kullanıyorsanız kodu değiştirmek için hala bir ihtiyaç vardır. Read_Committed_Snapshot deyim düzeyinde bir yalıtımdır, başka bir deyişle, yalnızca şu anda çalışan ifade için geçerlidir. Allow_Snapshot_Isolation, Begin Tran ve Commit arasındaki her şey, işlem düzeyinde yalıtımdır. Ayrı olarak bağlanabilirler, ancak satır başına aynı 14 baytlık ek yük kurulur.
Delux

Oluşturulan 14 baytlık ek binaya ek bilgi eklediğiniz için teşekkür ederiz. Kim videodan geçiyor ama burada da metinde olması çok yararlı.
Ali Razeghi

15

Tamam, eve döndü ve test edildi. İşte gözlem.

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

İlk olarak her iki ayar da KAPALI olarak onaylandı.

Sorgu 1

USE TEST;

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

--COMMIT;
--ROLLBACK;
GO

Sorgu 2

USE TEST;

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

Bu sınamada, sorgu 2, sorgu 1'in yerine getirilmesini bekliyor, dm_tran_locks DMV, 1. sıradaki TABLE1 üzerindeki özel kilidin olduğunu gösterir.

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'

İkinci test , önceki işlemi geri alma, READ_COMMITTED_SNAPSHOT ON ayarını yapın, ancak ALLOW_SNAPSHOT_ISOLATION OFF bırakın.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT ON
WITH ROLLBACK IMMEDIATE;
GO

Sorgu 1'i çalıştırın ve sorgu 2'yi çalıştırın. DMV, sorgu 1'i özel kilit içerdiğinde gösterir, ancak sorgu 2, sorgu 1 işlem yapmadan 'Orijinal' ile ayrıntıları döndürür. READ_COMMITTED satır versiyonunun yerinde olduğu anlaşılıyor.

SET TRANSACTION ISOLATION LEVEL SNAPSHOT;Sorgu 1 ve sorgu 2'ye ekleme ve sorgu 1 veya sorgu 2'yi çalıştırma hata döndürür - Anlık görüntü yalıtım işlemi bu veritabanında anlık görüntü yalıtımına izin verilmediğinden 'TEST' veritabanına erişilemedi. Anlık görüntü yalıtımına izin vermek için ALTER DATABASE kullanın.

Üçüncü test , önceki işlemi geri alma. READ_COMMITTED_SNAPSHOT OFF ve ALLOW_SNAPSHOT_ISOLATION ON ayarını yapın.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT OFF
WITH ROLLBACK IMMEDIATE;
GO

ALTER DATABASE TEST
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

Sorgu 1'i çalıştırın, ardından sorgu 2'yi çalıştırın. DMV, sorgu 1 tarafından yapılan özel kilidi gösterir. Sorgu 2, sorgu 1'in tamamlanmasını bekliyor gibi görünüyor. ALLOW_SNAPSHOT_ISOLATION ON işlevinin açılması, READ COMMITTED satır sürümünün etkinleştirilmesi için görünmüyor.

SET TRANSACTION ISOLATION LEVEL SNAPSHOT;Hem sorgu 1'e hem de sorgu 2'ye ekleme yapın . Sorgu 1'i ve ardından sorgu 2'yi çalıştırın. DMV, sorgu 1'i özel kilit içerdiğinde, sorgu 2'yi 'Orijinal' ile döndürür. Anlık görüntü yalıtımı yerinde görünüyor.

Testten gözlem yapılması READ_COMMITTED_SNAPSHOT, ALLOW_SNAPSHOT_ISOLATIONayardan bağımsız olarak READ COMMITTED satır versiyonunu kendiliğinden etkinleştirdiğini / devre dışı bıraktığını gösterir .


4

Anlayışınız doğru. Buradan kısa, temiz ve basit tanımı hoşuma gidiyor :

READ_COMMITTED_SNAPSHOT veritabanı seçeneği AÇIK olduğunda, okunan taahhüt edilen yalıtım seviyesini ayarlama işlemleri satır versiyonlamasını kullanır.

ALLOW_SNAPSHOT_ISOLATION veritabanı seçeneği AÇIK olduğunda, işlemler anlık görüntü yalıtım seviyesini ayarlayabilir.

Anlaşılan birçok yanlış anlama MS'in kendisinden geliyor. Örneğin, burada diyorlar:

READ_COMMITTED_SNAPSHOT veritabanı seçeneğini AÇIK olarak ayarlarsanız, veritabanı motoru verileri korumak için kilit kullanmak yerine, varsayılan olarak satır sürümü ve anlık görüntü yalıtımı kullanır .

Ancak, söz konusu "anlık görüntü yalıtımı" set transaction isolation level snapshot, uygulanan işlemin davranışına eşit değildir .

Fark gelince, güzel bir açıklama burada .

READ_COMMITTED_SNAPSHOT, READ_COMMITTED_ROW_VERSIONING veya benzeri bir şey olarak adlandırılmışsa, muhtemelen daha iyi olur. :)


0

Microsoft'un bu özetini beğendim :

READ_COMMITTED_SNAPSHOT ON seçeneğinin ayarlanması, varsayılan READ COMMITTED izolasyon seviyesi altındaki versiyonlanmış satırlara erişime izin verir. READ_COMMITTED_SNAPSHOT seçeneği KAPALI olarak ayarlanmışsa, sürümlenen satırlara erişmek için her oturum için Anlık Görüntü yalıtım seviyesini açıkça ayarlamanız gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.