SQL Server'da, okuma kilitleri nasıl çalışır?


17

Aşağıdaki uzun süren sorgum olduğunu varsayalım

UPDATE [Table1]
SET [Col1] = 'some value'
WHERE [Col2] -- some clause which selects thousands of rows

ve yukarıdaki sorgu çalışırken aşağıdaki sorgunun yürütüldüğünü varsayalım

SELECT *
FROM [Table1]

İlk sorgu, ilk sorgu yapılana kadar ikinci sorgunun çalışmasını engelliyor mu? Öyleyse, ilk sorgu ikinci sorgunun tüm satırlarda veya yalnızca WHERE yan tümcesinde yer alan satırlarda çalışmasını engelliyor mu?

DÜZENLE:

İkinci sorgunun

SELECT [Col1], [Col2]
FROM [Table1]
WHERE [Col2] -- some clause whose matching elements overlap those from
             -- the clause in the first query and which has additional matching elements

Yanıtlar:


14

Ben, size tavsiye SQL Server bir sorgu yürütür nasıl anlama okur nasıl bir açıklama vardır ve iş ve nasıl kilitleme eserler yazıyor.

10000ft görünüm aşağıdaki gibi gider:

  • okuma operatörleri daha önce okudukları veriler üzerinde paylaşılan kilitler alır okumadan okudukları
  • yazma operatörleri, verileri değiştirmeden önce değiştirdikleri veriler üzerinde özel kilitler alır
  • veri kilitleri sadece dizgidir, örn. veritabanı ve nesne tarafından okunan anahtarın bir karması.
  • Kilit Yöneticisi, Kilit Uyumluluk matrisine göre verilen tüm kilitlerin bir listesini tutar ve uyumsuzlukları algılar
  • uyumsuz istekler, onları engelleyen uyumsuz hibe serbest bırakılana kadar askıya alınır
  • operatörler, verileri daha yüksek düzeyde okuma veya güncelleme niyetinde olduğunu bildirmek için bir kilit hiyerarşisi kullanır (sayfa veya tablo düzeyinde, bölüm düzeyi seçeneklerini yok sayarak). Bu, operatörlerin her bir satırı kilitlemeden tüm tabloları kilitlemesini sağlar
  • kilit ömrü ve aralık kilitleri daha yüksek izolasyon seviyelerini zorlamak için kullanılır

Bu gerçekten buz berg'inin ucu. Konu çok geniş. Örneğinizde, kimse aslında neyin kilitlendiğiyle ilgili sorunuzu cevaplayamaz çünkü birçok faktöre bağlı olacaktır. Tabii ki, hiçbir uygulama birSELECT * FROM Table1 bir WHERE yan tümcesi eksik olduğu ve* . Bunlar kötü uygulamalardır, çünkü diğer şeylerin yanı sıra, tam olarak tartışmaya kilitleneceklerdir.

Okuma ve yazma kilitleriyle karşılaşırsanız, satır sürümlendirme ve anlık görüntü izolasyonuna bakmanız gerekir. Satır Sürüm Oluşturma Tabanlı İzolasyon Seviyelerini Anlama bölümünü okuyun .


Bir tablonun tüm içeriğine ihtiyacım olursa (içinde sadece 14 satır var)? SELECT * FROM Table1Tam olarak ihtiyacım olan şey bu ise nasıl kötü bir uygulama ?
Azimuth

1
*tek başına kötü bir uygulamadır çünkü tablo yapısı değiştiğinde uygulama genellikle kesilir (sonuçta beklenmeyen sütunlar görünür).
Remus Rusanu

3

Düzenleme: @ @ MaxVernon işaret ettiği gibi , aşağıdaki hiçbir şekilde NOLOCK kullanmak için bir öneri değildir ve ben çok iyi sadece işlem düzeyini ayarlamak READ UNCOMMITEDve negatif çağrışım getirmek daha orada durmasına izin bahsetmeliydimNOLOCK ve ilk etapta . Başlangıçta yayınlandığı gibi:

Hızlı ve basit "Evet, ilk sorgu, belirli bir dizin ipucu belirtilmediğinde ( NOLOCK , bazen" kirli okuma "olarak adlandırılır) veya ikinci sorgunun işlem yalıtım düzeyi READ UNCOMMITED(aynı şekilde çalışır) olarak ayarlanmadığı sürece ikinci sorguyu engeller , hayır, öyle değil. "

Karşılık olarak münhasır veya başka bir şekilde WITHikinci maddeye bir maddenin dahil edilmesini içeren soruda verilen ek ayrıntıya yanıt olarak, SELECTiki sorgu arasındaki etkileşimler büyük ölçüde aynı olacaktır.

IF NOT EXISTS ( SELECT  1
                FROM    sys.objects
                WHERE   name = 'Foo'
                    AND type = 'U' )
BEGIN
    --DROP TABLE dbo.Foo;
    CREATE TABLE dbo.Foo
    (
        Foo_PK          BIGINT IDENTITY( 1, 1 ) NOT NULL,
                            PRIMARY KEY ( Foo_PK ),
        Bar             BIT,
        x               BIT,
        y               BIT,
        z               BIT
    );

    CREATE NONCLUSTERED INDEX IX_Foo_x
        ON  dbo.Foo ( x );

    INSERT INTO dbo.Foo ( Bar, x, y, z )
    VALUES ( 1, 1, 1, 1 ), ( 0, 0, 0, 0 );
END;    
GO

BEGIN TRANSACTION;

UPDATE  dbo.Foo
    SET y = 0
WHERE   x = 1;

-- COMMIT TRANSACTION;

Ayrı bir oturumda aşağıdakileri çalıştırın:

SELECT  *
FROM    dbo.Foo WITH ( NOLOCK );
GO

SELECT  *
FROM    dbo.Foo;

Şu anda tutulan kilitleri sp_lock, tercihen başka bir ayrı oturumda çalıştırarak inceleyebilirsiniz :

EXECUTE dbo.sp_lock;

KEYEkleme işlemini gerçekleştiren örümcek tarafından X(özel) modda tutulan , diğer IX(Intent-Exclusive) kilitlerle karıştırılmaması gereken bir tür kilit görmeniz gerekir . Kilit belgeleri ise gösterir KEYkilit menzil-özgü, aynı zamanda, içinde bu nedenle, orijinal sorgu bu aralık içinde düşebilir ihtiva sokulması veya veri değiştirilmesiyle etkilenen sütun güncelleme diğer işlemleri önler. Tutuluyor kilidi kendisi özeldir gibi, ilk sorgu gelen kaynağa erişim engelliyor herhangi başka eşzamanlı işlem. Aslında, ilk sorgu tarafından belirtilen aralığa dahil olsun ya da olmasın, sütunun tüm satırları kilitlenir.

Böylece Sikinci oturum tarafından tutulan kilit WAIT, Xkilit temizlenene kadar , ikinci oturum okuma işlemini tamamlamadan başka bir X(veya U) kilidin bu kaynak üzerinde farklı bir eşzamanlı hızdan alınmasını önleyerek kilidin varlığını haklı çıkarır S.

Şimdi netlik için bir düzenleme: Burada belirtilen risklerin kısa açıklamasından kirli bir okunan şeyde yanlış olmadıkça ... Düzen 3 : Bir fark yazan bir arka plan kontrol noktasının etkisini düşünmediğimi fark ettim diske henüz taahhüt edilmemiş işlem, bu yüzden evet, benim açıklama yanıltıcı oldu.

İkinci sorguda, ilk toplu iş taahhüt edilmemiş verileri döndürebilir (ve bu durumda). Varsayılan işlem yalıtım düzeyinde çalışan ikinci toplu iş READ COMMITEDyalnızca ilk oturumda bir kesinleştirme veya geri alma işlemi tamamlandıktan sonra geri döner.

Buradan kendi sorgu planları ve ilgili kilit seviyelerinde bakabilirsiniz, ama daha iyisi, SQL Server kilitleri hakkında tüm okuyabilirsiniz burada .


1
WITH (NOLOCK)Bu durumda kullanımla ilgili bir uyarı kelimesi yararlı olacaktır. Daha fazla okuma için brentozar.com/archive/2011/11/… ve brentozar.com/archive/2013/02/… adresine bakın .
Max Vernon

3
Ah, WITH (NOLOCK)ipucu işlenmemiş kirli sayfaları bellekten döndürmez. Aslında, yazarların tablonun kullandığı sayfalara güncelleme yapmasını veya satır eklemesini engellemeden tablodaki satırları (ister diskte ister önbellekte olsun) okur.
Max Vernon

2
Kafam karıştı. "1. sorgu, 2. sorgunun çalışmasını engelliyor mu?" Hayır, ikinci sorunun cevabı nasıl "Evet" olabilir? Hangi soruları cevapladığınızı açıklığa kavuşturabilir ve yanıtlarınızı genişletebilir misiniz?
Tüm

Düzenlemeler bolca, üzgünüm millet! Açık olmayan başka bir şey varsa bana bildirin!
Avarkx
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.