Aracılığıyla paylaş


Kilitlenme rehberi

Şunlar için geçerlidir:SQL ServerAzure SQL VeritabanıAzure SQL Yönetilen ÖrneğiAzure Synapse AnalyticsAnalytics Platform Sistemi (PDW)Microsoft Fabric'te SQL Veritabanı

Bu makalede Veritabanı Altyapısı'ndaki kilitlenmeler ayrıntılı olarak ele alınmaktadır. Kilitlenmeler, genellikle çok adımlı işlemlerde veritabanındaki rakip, eşzamanlı kilitlerden kaynaklanmaktadır. İşlemler ve kilitler hakkında daha fazla bilgi için bkz. İşlem kilitleme ve satır sürüm oluşturma kılavuzu.

Azure SQL Veritabanı'nda ve Doku'daki SQL veritabanında kilitlenmeleri tanımlama ve önleme hakkında daha ayrıntılı bilgi için bkz. Azure SQL Veritabanı'nda ve Doku'daki SQL veritabanında kilitlenmeleri analiz etme ve önleme.

Kilitlenmeleri anlama

İki veya daha fazla görev, diğer görevlerin kilitlemeye çalıştığı bir kaynakta kilit sahibi olan her görevin birbirini kalıcı olarak engellemesi durumunda kilitlenme oluşur. Örneğin:

  • A İşlemi, 1. satır üzerinde paylaşımlı bir kilit edinir.

  • İşlem B, 2. satıra paylaşımlı bir kilit alır.

  • A işlemi artık 2. satırda özel bir kilit istemektedir ve B işlemi tamamlanıp 2. satırda bulunan paylaşılan kilidi serbest bırakana kadar engellenir.

  • B işlemi artık 1. satırda özel bir kilit istemektedir ve A işlemi 1. satırdaki paylaşılan kilidi tamamlayıp serbest bırakana kadar engellenir.

A işlemi B işlemi tamamlanana kadar tamamlayamaz, ancak B işlemi A işlemi tarafından engellenir. Bu koşul döngüsel bağımlılık olarak da adlandırılır: A İşleminin B işlemine bağımlılığı vardır ve B işlemi A işlemine bağımlı olarak daireyi kapatır.

Kilitlenme bir dış işlem tarafından bozulmadığı sürece, kilitlenmedeki her iki işlem de sonsuza kadar bekler. Veritabanı Altyapısı kilitlenme izleyicisi, kilitlenme içindeki görevleri düzenli aralıklarla denetler. İzleyici döngüsel bir bağımlılık algılarsa, görevlerden birini kurban olarak seçer ve işlemini bir hatayla sonlandırır. Bu, diğer görevin işlemini tamamlayabilmesini sağlar. Bir hatayla sonlandırılan işlemle uygulama işlemi yeniden deneyebilir ve bu işlem genellikle diğer kilitlenme işlemi tamamlandıktan sonra tamamlanır.

Kilitlenme genellikle normal engellenme ile karıştırılır. bir işlem başka bir işlem tarafından kilitlenen bir kaynak üzerinde kilit istediğinde, istekte bulunan işlem kilit serbest bırakılana kadar bekler. Varsayılan olarak Veritabanı Altyapısı'ndaki işlemler, LOCK_TIMEOUT ayarlanmadığı sürece zamanaşımına uğramaz. İstekte bulunan işlem kilidin sahibi olan işlemi engellemek için herhangi bir işlem yapmadığından istekte bulunan işlem engellenir, kilitlenmez. Sonunda, sahip olan işlem kilidi tamamlar ve kilidi serbest bırakır, ardından istekte bulunan işleme kilit verilir ve işlem devam eder. Kilitlenmeler neredeyse hemen çözülürken engelleme teoride süresiz olarak devam edebilir. Kilitlenmeler bazen ölümcül sıkışma olarak adlandırılır.

Kilitlenme, yalnızca ilişkisel veritabanı yönetim sisteminde değil, birden çok iş parçacığına sahip herhangi bir sistemde oluşabilir ve veritabanı nesneleri üzerindeki kilitler dışındaki kaynaklar için oluşabilir. Örneğin, çok iş parçacıklı bir işletim sistemindeki bir iş parçacığı bellek blokları gibi bir veya daha fazla kaynak alabilir. Alınan kaynak şu anda başka bir iş parçacığına aitse, ilk iş parçacığı hedef kaynağın serbest bırakılması için sahip olan iş parçacığını beklemek zorunda kalabilir. Bekleyen iş parçacığının söz konusu kaynak için sahip olan iş parçacığına bağımlılığı olduğu söylenir. Veritabanı Motorunun bir örneğinde, bellek veya iş parçacıkları gibi veritabanı dışı kaynaklar elde edilirken oturumlar çıkmaza girebilir.

İşlem kilitlenmesi gösteren diyagram.

Çizimde, T1 işleminin tablo kilitleme kaynağı için T2 işlemine Part bağımlılığı vardır. Benzer şekilde, T2 işleminin tablo kilitleme kaynağı için T1 işlemine Supplier bağımlılığı vardır. Bu bağımlılıklar bir döngü oluşturduğundan, T1 ve T2 işlemleri arasında bir kilitlenme vardır.

Kilitlenmenin daha genel bir çizimi aşağıdadır:

Kilitlenme durumundaki görevleri gösteren diyagram.

  • T1 görevi, R1 kaynağında bir kilide sahiptir (R1'den T1'e doğru okla gösterilir) ve R2 kaynağında bir kilit talep etmiştir (T1'den R2'ye doğru okla gösterilir).

  • T2, R2 kaynağında bir kilide sahiptir (R2'den T2'ye yönelen okla gösterilir) ve R1 kaynağında bir kilit talep etti (T2'den R1'e yönelen okla gösterilir).

  • Bir kaynak kullanılabilir olana kadar hiçbir görev devam etemediği ve görev devam edene kadar hiçbir kaynak serbest bırakılamadığı için kilitlenme durumu vardır.

Note

Veritabanı Altyapısı kilitlenme döngülerini otomatik olarak algılar. İşlemlerden birini kilitlenme kurbanı olarak seçer ve kilitlenmeyi bozmak için bu işlemi bir hata mesajıyla sonlandırır.

Kilitlenmeye neden olabilecek kaynaklar

Her kullanıcı oturumunda, kendi adına çalışan ve kaynak elde edebilecek veya edinmek için bekleyebilecek bir veya birden fazla görev olabilir. Aşağıdaki kaynak türleri kilitlenmeye neden olabilecek engellemelere neden olabilir.

  • Locks. Kaynaklar üzerinde kilitlerin alınmasını beklemek, örneğin nesneler, sayfalar, satırlar, meta veriler ve uygulamalar, kilitlenmelere sebep olabilir. Örneğin, T1 işleminin r1 satırında paylaşılan (S) bir kilidi vardır ve r2'de özel (X) bir kilit almayı bekler. İşlem T2'nin r2 üzerinde paylaşılan (S) bir kilidi vardır ve r1 satırında özel (X) kilit almayı bekliyor. Bu, T1 ve T2'nin birbirinin kilitli kaynaklarını serbest bırakmasını beklediği bir kilitlenme döngüsüne yol açar.

  • Çalışan iş parçacıkları. Kuyruğa alınmış bir görev, bir çalışan iş parçacığı kullanılabilir olana kadar beklerken kilitlenmeye neden olabilir. Kuyruğa alınan görev, tüm çalışan iş parçacıklarını engelleyen kaynaklara sahipse, bir kilitlenme meydana gelir. Örneğin, S1 oturumu bir işlem başlatır ve r1 satırında paylaşılan (S) bir kilit alır ve ardından bekleme moduna geçer. Kullanılabilir tüm çalışan iş parçacıklarında çalışan etkin oturumlar, r1 satırında özel (X) kilitler almaya çalışıyor. Oturum S1 bir çalışan iş parçacığını alamadığı için işlemi işleyemez ve kilidi r1 satırında serbest bırakamaz. Bu da kilitlenmeye neden olur.

  • Memory. Eşzamanlı istekler, mevcut bellekle karşılanamadığında bellek izinlerini beklerken bir kilitlenme meydana gelebilir. Örneğin, Q1 ve Q2 gibi iki eşzamanlı sorgu, sırasıyla 10 MB ve 20 MB bellek elde eden kullanıcı tanımlı işlevler olarak yürütülür. Her sorgu için 30 MB gerekiyorsa ve toplam kullanılabilir bellek 20 MB ise, Q1 ve Q2'nin bellek serbest bırakmak için birbirlerini beklemesi gerekir ve bu da kilitlenmeye neden olur.

  • Paralel sorgu yürütmeyle ilgili kaynaklar. Değişim bağlantı noktasıyla ilişkili koordinatör, üretici veya tüketici iş parçacıkları, genellikle paralel sorgunun bir parçası olmayan en az bir başka işlem eklendiğinde birbirlerini engelleyebilir ve bu da kilitlenmelere yol açabilir. Ayrıca, paralel sorgu yürütmeye başladığında Veritabanı Altyapısı paralellik derecesini ve geçerli iş yüküne bağlı olarak gerekli çalışan iş parçacığı sayısını belirler. Sistem iş yükü beklenmedik şekilde değişirse (örneğin, sunucuda yeni sorgular çalışmaya başlarsa veya sistemde çalışan iş parçacıkları tükenirse) kilitlenme oluşabilir.

  • Birden çok Etkin Sonuç Kümesi (MARS) kaynağı. Bu kaynaklar, MARS altında birden çok etkin isteğin iç içe geçirilmesini denetlemek için kullanılır. Daha fazla bilgi için bkz. SQL Server Yerel İstemcisinde Birden Çok Etkin Sonuç Kümesi (MARS) Kullanma.

    • Kullanıcı kaynağı. bir iş parçacığı, potansiyel olarak bir kullanıcı uygulaması tarafından denetlenen bir kaynağı beklerken, bu kaynak bir dış veya kullanıcı kaynağı olarak sayılır ve kilit gibi muamele görür.

    • Oturum kilitleyici. Bir oturumda çalışan görevler birbirine eklenir; başka bir deyişle, belirli bir anda oturum altında yalnızca bir görev çalıştırılabilir. Görevin çalıştırılabilmesi için önce oturumdaki mutex'e özel erişime sahip olması gerekir.

    • İşlem muteksi. Tek bir işlemde çalışan tüm görevler birbirine eklenir, yani belirli bir anda işlem altında yalnızca bir görev çalıştırılabilir. Görevin çalıştırılabilmesi için önce işlem mutex'ine özel erişime sahip olması gerekir.

      Bir görevin MARS altında çalışması için oturum mutex'ini alması gerekir. Görev bir işlem altında çalışıyorsa işlem mutex'ini alması gerekir. Bu, belirli bir oturumda ve belirli bir işlemde bir kerede yalnızca bir görevin etkin olduğunu garanti eder. Gerekli mutex'ler alındıktan sonra görev yürütülebilir. Görev tamamlandığında veya isteğin ortasında bir sonuç verdiğinde, ilk olarak işlem mutex'ini serbest bırakır, ardından kazanma sırasının tersine oturum mutex'ini serbest bırakır. Ancak, bu kaynaklarda kilitlenmeler oluşabilir. Aşağıdaki sahte kodda, kullanıcı isteği U1 ve kullanıcı isteği U2 adlı iki görev aynı oturumda çalışır.

      U1:    Rs1=Command1.Execute("insert sometable EXEC usp_someproc");
      U2:    Rs2=Command2.Execute("select colA from sometable");
      

      Kullanıcı isteği U1'den yürütülen saklı yordam, oturum mutex'ini aldı. Saklı yordamın yürütülmesi uzun sürüyorsa, Veritabanı Altyapısı tarafından saklı yordamın kullanıcıdan giriş beklediği varsayılır. Kullanıcı isteği U2, kullanıcı U2'den sonuç kümesini beklerken oturum mutex'ini bekliyor ve U1 bir kullanıcı kaynağını bekliyor. Bu kilitlenme durumu mantıksal olarak şu şekilde gösterilmiştir:

      Saklı bir yordamın mantıksal akış diyagramı MARS'ta.

Kilitlenmeler, bir tablo bölümlendiğinde ve LOCK_ESCALATION ayarı ALTER TABLE olarak ayarlandığında, AUTO'da da oluşabilir. LOCK_ESCALATION olarak ayarlandığındaAUTO, Veritabanı Altyapısı'nın tablo bölümlerini tablo düzeyinde değil HoBT düzeyinde kilitlemesine izin vererek eşzamanlılık artar. Ancak ayrı işlemler bir tabloda bölüm kilitlerini barındırdığında ve diğer işlemler bölümünde bir yerde kilit olmasını istediğinde, bu kilitlenmeye neden olur. Bu tür bir kilitlenme, LOCK_ESCALATIONTABLE olarak ayarlanmasıyla önlenebilir. Ancak bu ayar, bir bölümdeki büyük güncelleştirmeleri tablo kilidini beklemeye zorlayarak eşzamanlılığı azaltır.

Kilitlenme algılama

Kilitlenmeye neden olabilecek kaynaklar bölümünde listelenen tüm kaynaklar Veritabanı Altyapısı kilitlenme algılama düzenine katılır. Kilitlenme algılama, Veritabanı Motoru örneğindeki tüm görevler arasında düzenli aralıklarla arama başlatan bir kilit izleme iş parçacığı tarafından gerçekleştirilir. Aşağıdaki noktalar arama işlemini açıklar:

  • Varsayılan aralık 5 saniyedir.

  • Kilit izleme iş parçacığı çıkmazları bulursa, çıkmaz algılama süresi, çıkmazların sıklığına bağlı olarak 5 saniyeden 100 milisaniyeye kadar düşer.

  • Kilit izleyicisi iş parçacığı kilitlenmeleri bulmayı durdurursa, Veritabanı Altyapısı aramalar arasındaki aralıkları 5 saniyeye artırır.

  • Kilitlenme algılanırsa, kilit beklemesi gereken yeni iş parçacıklarının kilitlenme döngüsüne girdiği varsayılır. Kilitlenme algılandıktan sonra, ilk birkaç kilit bekleme, bir sonraki kilitlenme algılama aralığını beklemek yerine hemen bir kilitlenme araması tetikler. Örneğin, geçerli aralık 5 saniye ise ve kilitlenme yeni algılandıysa, sonraki kilit bekleme işlemi kilitlenme algılayıcısını hemen başlatır. Bu kilit bekleme bir kilitlenmenin parçasıysa, bir sonraki kilitlenme araması yerine hemen algılanır.

Veritabanı Altyapısı genellikle yalnızca düzenli aralıklarla kilitlenme algılaması gerçekleştirir. Sistemde karşılaşılan kilitlenme sayısı genellikle küçük olduğundan, düzenli kilitlenme algılama sistemindeki kilitlenme algılama yükünü azaltmaya yardımcı olur.

Kilit izleyicisi belirli bir iş parçacığı için kilitlenme tespiti araması başlattığında, iş parçacığının beklemekte olduğu kaynağı tanımlar. Kilit izleyicisi daha sonra söz konusu kaynağın sahiplerini bulur ve bir döngü bulana kadar bu iş parçacıkları için yinelemeli olarak kilitlenme aramasını sürdürür. Bu şekilde tanımlanan bir döngü kilitlenme oluşturur.

Kilitlenme algılandıktan sonra Veritabanı Altyapısı, iş parçacıklarından birini kilitlenme kurbanı olarak seçerek kilitlenmeyi sonlandırır. Veritabanı Altyapısı iş parçacığı için yürütülen geçerli toplu işlemi sonlandırır, kilitlenme kurbanının işlemini geri alır ve uygulamaya 1205 hatasını döndürür. Kilitlenme kurbanı olan işlemin geri alınması, işlem tarafından tutulan tüm kilitlerin serbest bırakılmasını sağlar. Bu, diğer iş parçacıklarının işlemlerinin engelinin kaldırılıp devam etmesini sağlar. 1205 (kilitlenme kurbanı) hatası, kilitlenmeye dahil olan kaynakların türüyle ilgili bilgileri kaydeder.

Varsayılan olarak Veritabanı Altyapısı, kilitlenme kurbanı olarak geri alınması en düşük maliyetli işlemi çalıştıran işlemi seçer. Alternatif olarak, SET DEADLOCK_PRIORITY deyimini kullanarak, bir kullanıcı kilitlenme durumunda oturumların önceliğini belirtebilir. DEADLOCK_PRIORITY, LOW, veya NORMALolarak ayarlanabilir HIGHveya alternatif olarak -10 ile 10 aralığındaki herhangi bir tamsayı değerine ayarlanabilir. Bazı durumlarda Veritabanı Altyapısı, daha iyi eşzamanlılık elde etmek için kilitlenme önceliğini kısa bir süre için değiştirmeyi tercih edebilir.

Kilitlenme önceliği varsayılan olarak NORMAL, yani 0 olarak belirlenmiştir. İki oturumun kilitlenme öncelikleri farklıysa, düşük önceliğe sahip oturumdaki işlem kilitlenme kurbanı olarak seçilir. Her iki oturum da aynı kilitlenme önceliğine sahipse, geri alınması en düşük maliyetli işlem seçilir. Kilitlenme döngüsüne dahil olan oturumlar aynı kilitlenme önceliğine ve aynı maliyete sahipse, rastgele bir kurban seçilir. Geri dönen bir görev kilitlenme kurbanı olarak seçilemiyor.

Ortak dil çalışma zamanı (CLR) ile çalışırken, kilitlenme izleme mekanizması, yönetilen yordamların içinde erişilen eşitleme kaynakları (izleyiciler, okuyucu/yazıcı kilidi ve iş parçacığını birleştirme) için kilitlenmeleri otomatik olarak algılar. Ancak kilitlenme, kilitlenme kurbanı olarak seçilen yordamda bir özel durum oluşturularak çözülür. Özel durumun şu anda kurbana ait kaynakları otomatik olarak yayınlamadığını anlamak önemlidir; kaynakların açıkça yayımlanması gerekir. Özel durum davranışıyla tutarlı olarak, kilitlenme kurbanını tanımlamak için kullanılan özel durum yakalanabilir ve görmezden gelinebilir.

Kilitlenme analiz araçları

Veritabanı Altyapısı, kilitlenme bilgilerini görüntülemek için xml_deadlock_report uzatılmış olayı, iki izleme bayrağını ve SQL Profiler'daki kilitlenme grafiği olayını içeren izleme araçları sağlar.

Genişletilmiş xml_deadlock_report olayı, kilitlenme bilgilerini yakalamak için önerilen yöntemdir.

Kilitlenme uzatılmış olayı

SQL Server 2012 (11.x) ve sonraki sürümlerinde, xml_deadlock_report SQL Trace veya SQL Profiler'daki kilitlenme grafiği olay sınıfı yerine genişletilmiş olay kullanılmalıdır.

system_health olay oturumu varsayılan olarak olayları yakalarxml_deadlock_report. Bu olaylar kilitlenme grafiğini içerir. Oturum varsayılan olarak etkinleştirildiğinden system_health kilitlenme bilgilerini yakalamak için ayrı bir olay oturumu yapılandırmanız gerekmez.

Yakalanan kilitlenme grafiğinde genellikle üç ayrı düğüm vardır:

  • victim-list. Kilitlenme kurbanı işlem tanımlayıcısı.
  • process-list. Kilitlenmeye dahil olan tüm süreçlerle ilgili bilgiler.
  • resource-list. Kilitlenmeye dahil olan kaynaklar hakkında bilgi.

Oturumun event_file hedef verilerini system_health Management Studio'da görüntüleyebilirsiniz. Herhangi bir xml_deadlock_report olay meydana gelirse, Management Studio aşağıdaki örnekte görüldüğü gibi kilitlenmeye neden olan görevlerin ve kaynakların grafik bir gösterimini sunar:

XEvent Kilitlenme Grafı görsel diyagramının SSMS'sinden ekran görüntüsü.

Aşağıdaki sorgu, ring_buffer oturumunun system_health hedefi tarafından yakalanan tüm kilitlenme olaylarını görüntüleyebilir.

SELECT xdr.value('@timestamp', 'datetime') AS deadlock_time,
       xdr.query('.') AS event_data
FROM (SELECT CAST ([target_data] AS XML) AS target_data
      FROM sys.dm_xe_session_targets AS xt
           INNER JOIN sys.dm_xe_sessions AS xs
               ON xs.address = xt.event_session_address
      WHERE xs.name = N'system_health'
            AND xt.target_name = N'ring_buffer') AS XML_Data
CROSS APPLY Target_Data.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS XEventData(xdr)
ORDER BY deadlock_time DESC;

Sonuç kümesi aşağıdadır.

system_health XEvent sorgu sonucunun SSMS'sinden ekran görüntüsü.

Aşağıdaki örnek, event_data sütununun çıktısının bir örneğini göstermektedir:

<event name="xml_deadlock_report" package="sqlserver" timestamp="2022-02-18T08:26:24.698Z">
  <data name="xml_report">
    <type name="xml" package="package0" />
    <value>
      <deadlock>
        <victim-list>
          <victimProcess id="process27b9b0b9848" />
        </victim-list>
        <process-list>
          <process id="process27b9b0b9848" taskpriority="0" logused="0" waitresource="KEY: 5:72057594214350848 (1a39e6095155)" waittime="1631" ownerId="11088595" transactionname="SELECT" lasttranstarted="2022-02-18T00:26:23.073" XDES="0x27b9f79fac0" lockMode="S" schedulerid="9" kpid="15336" status="suspended" spid="62" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2022-02-18T00:26:22.893" lastbatchcompleted="2022-02-18T00:26:22.890" lastattention="1900-01-01T00:00:00.890" clientapp="SQLCMD" hostname="ContosoServer" hostpid="7908" loginname="CONTOSO\user" isolationlevel="read committed (2)" xactid="11088595" currentdb="5" lockTimeout="4294967295" clientoption1="538968096" clientoption2="128056">
            <executionStack>
              <frame procname="AdventureWorks2022.dbo.p1" line="3" stmtstart="78" stmtend="180" sqlhandle="0x0300050020766505ca3e07008ba8000001000000000000000000000000000000000000000000000000000000">
SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+    </frame>
              <frame procname="adhoc" line="4" stmtstart="82" stmtend="98" sqlhandle="0x020000006263ec01ebb919c335024a072a2699958d3fcce60000000000000000000000000000000000000000">
unknown    </frame>
            </executionStack>
            <inputbuf>
SET NOCOUNT ON
WHILE (1=1)
BEGIN
    EXEC p1 4
END
   </inputbuf>
          </process>
          <process id="process27b9ee33c28" taskpriority="0" logused="252" waitresource="KEY: 5:72057594214416384 (e5b3d7e750dd)" waittime="1631" ownerId="11088593" transactionname="UPDATE" lasttranstarted="2022-02-18T00:26:23.073" XDES="0x27ba15a4490" lockMode="X" schedulerid="6" kpid="5584" status="suspended" spid="58" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2022-02-18T00:26:22.890" lastbatchcompleted="2022-02-18T00:26:22.890" lastattention="1900-01-01T00:00:00.890" clientapp="SQLCMD" hostname="ContosoServer" hostpid="15316" loginname="CONTOSO\user" isolationlevel="read committed (2)" xactid="11088593" currentdb="5" lockTimeout="4294967295" clientoption1="538968096" clientoption2="128056">
            <executionStack>
              <frame procname="AdventureWorks2022.dbo.p2" line="3" stmtstart="76" stmtend="150" sqlhandle="0x03000500599a5906ce3e07008ba8000001000000000000000000000000000000000000000000000000000000">
UPDATE t1 SET c2 = c2+1 WHERE c1 = @p    </frame>
              <frame procname="adhoc" line="4" stmtstart="82" stmtend="98" sqlhandle="0x02000000008fe521e5fb1099410048c5743ff7da04b2047b0000000000000000000000000000000000000000">
unknown    </frame>
            </executionStack>
            <inputbuf>
SET NOCOUNT ON
WHILE (1=1)
BEGIN
    EXEC p2 4
END
   </inputbuf>
          </process>
        </process-list>
        <resource-list>
          <keylock hobtid="72057594214350848" dbid="5" objectname="AdventureWorks2022.dbo.t1" indexname="cidx" id="lock27b9dd26a00" mode="X" associatedObjectId="72057594214350848">
            <owner-list>
              <owner id="process27b9ee33c28" mode="X" />
            </owner-list>
            <waiter-list>
              <waiter id="process27b9b0b9848" mode="S" requestType="wait" />
            </waiter-list>
          </keylock>
          <keylock hobtid="72057594214416384" dbid="5" objectname="AdventureWorks2022.dbo.t1" indexname="idx1" id="lock27afa392600" mode="S" associatedObjectId="72057594214416384">
            <owner-list>
              <owner id="process27b9b0b9848" mode="S" />
            </owner-list>
            <waiter-list>
              <waiter id="process27b9ee33c28" mode="X" requestType="wait" />
            </waiter-list>
          </keylock>
        </resource-list>
      </deadlock>
    </value>
  </data>
</event>

İzleme bayrağı 1204 ve izleme bayrağı 1222

Kilitlenmeler oluştuğunda ve izleme bayrağı 1204 veya izleme bayrağı 1222 etkinleştirildiğinde, kilitlenme ayrıntıları SQL Server hata günlüğünde bildirilir. İzleme bayrağı 1204, kilitlenmeye dahil olan her düğüm tarafından biçimlendirilmiş kilitlenme bilgilerini raporlar. İzleme bayrağı 1222, kilitlenme bilgilerini önce işlemlere, sonra da kaynaklara göre biçimlendirmektedir. Aynı kilitlenme olayının iki gösterimini almak için her iki izleme bayrağını da etkinleştirmek mümkündür.

Important

Kilitlenmelerle karşılaşan iş yükü yoğunluklu sistemlerde izleme bayrakları 1204 ve 1222 kullanmaktan kaçının. Bu izleme bayraklarının kullanılması performans sorunlarına neden olabilir. Bunun yerine, gerekli bilgileri yakalamak için Tıkalı durum genişletilmiş olayını kullanın.

Aşağıdaki tabloda, 1204 ve 1222 izleme bayraklarının özelliklerini tanımlamanın yanı sıra benzerlikler ve farklılıklar da gösterilmektedir.

Property İzleme bayrağı 1204 ve izleme bayrağı 1222 Yalnızca izleme bayrağı 1204 Yalnızca izleme işareti 1222
Çıkış biçimi Çıkış, SQL Server hata günlüğünde yakalanır. Kilitlenmeye dahil olan düğümlere odaklandı. Her bir düğüm için ayrılmış bir bölüm vardır ve son bölümde kilitlenme kurbanı tanımlanıyor. XML Şema Tanımı (XSD) şemasına uymayan XML benzeri bir biçimde bilgi döndürür. Biçimin üç ana bölümü vardır. İlk bölümde kilitlenme kurbanı ilan edilir. İkinci bölümde kilitlenmeye dahil olan her işlem açıklanır. Üçüncü bölümde, 1204 izleme bayrağındaki düğümlerle eş anlamlı olan kaynaklar açıklanmaktadır.
Öznitelikleri tanımlama SPID:<x> ECID:<x>. Paralel işlemler için oturum kimliği iş parçacığını tanımlar. SPID:<x> ECID:0 girdisi, <x> SPID değeriyle değiştirildiğinde, ana iş parçacığını temsil eder. SPID değeriyle değiştirildiği ve SPID:<x> ECID:<y> 0'dan büyük olan <x> girdisi, aynı SPID için yürütme bağlamını temsil eder.

BatchID (sbid 1222 izleme bayrağı için). Kod yürütmenin kilit istediği veya tuttuğu toplu işlem grubunu tanımlar. Birden Çok Etkin Sonuç Kümesi (MARS) devre dışı bırakıldığında BatchID değeri 0 olur. MARS etkinleştirildiğinde etkin toplu işlemler için değer 1 ile n arasında olur. Oturumda etkin toplu iş yoksa BatchID değeri 0'dır.

Mode bir iş parçacığı tarafından istenen, verilen veya bekleyen belirli bir kaynak için kilit türünü belirtir. Mod Intent Shared (IS), Shared, Update (S), Intent Exclusive (U), Shared with Intent Exclusive (IX) ve Exclusive (SIX) olabilir.

Line # (line 1222 izleme bayrağı için). Kilitlenme meydana geldiğinde yürütülmekte olan mevcut toplu işlemlerdeki satır numarasını listeler.

Input Buf (inputbuf 1222 izleme bayrağı için). Şu anki toplu işteki tüm deyimleri listeler.
Node Kilitlenme zincirindeki giriş numarasını temsil eder.

Lists Kilit sahibi şu listelerin bir parçası olabilir:

Grant List Kaynağın geçerli sahiplerini numaralandırır.

Convert List Kilitlerini daha üst bir seviyeye yükseltmeye çalışan mevcut sahipleri numaralandırır.

Wait List Kaynak için geçerli yeni kilit isteklerini numaralandırır.

Statement Type İş parçacıklarının izinlerinin bulunduğu ifadenin türünü (SELECT, INSERT, UPDATE veya DELETE) açıklar.

Victim Resource Owner Veritabanı Altyapısı'nın kilitlenme döngüsünü kesmek için kurban olarak seçtiği katılımcı iş parçacığını belirtir. Seçilen iş parçacığı ve tüm yürütme bağlamları sonlandırılır.

Next Branch Kilitlenme döngüsünde yer alan aynı SPID'den iki veya daha fazla yürütme bağlamını temsil eder.
deadlock victim Kilitlenme kurbanı olarak seçilen görevin fiziksel bellek adresini temsil eder (bkz. sys.dm_os_tasks). Çözümlenmemiş kilitlenme durumunda değer sıfır olabilir.

executionstack Kilitlenme oluştuğu sırada yürütülen Transact-SQL çağrı yığınını temsil eder.

priority Kilitlenme önceliğini temsil eder.

logused İşlem tarafından kullanılan log dosyası alanı.

owner id İsteğin denetimine sahip olan işlemin kimliği.

status Görevin durumu. Daha fazla bilgi için bkz. sys.dm_os_tasks.

waitresource Görevin gerektirdiği kaynak.

waittime Milisaniye olarak kaynağı bekleme süresi.

schedulerid Bu görevle ilişkili zamanlayıcı. Bkz. sys.dm_os_schedulers.

hostname İş istasyonunun adı.

isolationlevel Geçerli işlem yalıtım düzeyi.

Xactid İsteğin denetimine sahip olan işlemin kimliği.

currentdb Veritabanının kimliği.

lastbatchstarted İstemci işleminin toplu yürütmeyi en son başlattığı zaman.

lastbatchcompleted İstemci işleminin toplu yürütmeyi tamamladığı en son zaman.

clientoption1 ve clientoption2 Bu oturumdaki ayar seçenekleri. Bu değerler, genellikle SET gibi SET NOCOUNT ve SET XACTABORT deyimleriyle denetlenen seçenekleri temsil eden bitmasklerdir. Daha fazla bilgi için bkz. @@OPTIONS.

associatedObjectId HoBT (yığın veya B ağacı) kimliğini temsil eder.
Kaynak öznitelikleri RID , üzerinde kilit tutulan veya istenen tablodaki tek satırı tanımlar. RID, RID olarak temsil edilir: db_id:file_id:page_no:row_no. Örneğin, RID: 6:1:20789:0.

OBJECT bir kilidin tutıldığı veya istendiği tabloyu tanımlar. OBJECT olarak OBJECT: db_id:object_idtemsil edilir. Örneğin, TAB: 6:2009058193.

KEY Bir kilidin tutıldığı veya istendiği dizin içindeki anahtar aralığını tanımlar. KEY, db_id:hobt_id (dizin anahtarı karma değeri) olarak temsil edilir. Örneğin, KEY: 6:72057594057457664 (350007a4d329).

PAG Kilidin tutıldığı veya istendiği sayfa kaynağını tanımlar. PAG olarak PAG: db_id:file_id:page_notemsil edilir. Örneğin, PAG: 6:1:20789.

EXT Kapsam yapısını tanımlar. EXT olarak EXT: db_id:file_id:extent_notemsil edilir. Örneğin, EXT: 6:1:9.

DB Veritabanı kilidini tanımlar. DB aşağıdaki yollardan biriyle gösterilir:

DB: db_id

DB: db_id[BULK-OP-DB], veritabanı yedeklemesi tarafından alınan veritabanı kilidini tanımlar.

DB: db_id[BULK-OP-LOG], günlük yedekleme tarafından alınan kilidi tanımlar.

APP Uygulama kilidini tanımlar. APP olarak APP: lock_resourcetemsil edilir. Örneğin, APP: Formf370f478.

METADATA Kilitlenmeye dahil olan meta veri kaynaklarını temsil eder. Birçok alt kaynağı olduğundan METADATA , döndürülen değer kilitlenmeye neden olan alt kaynağa bağlıdır. Örneğin, METADATA.USER_TYPEuser_type_id = *integer_value*döndürür. Kaynaklar ve alt kaynaklar hakkında METADATA daha fazla bilgi için bkz. sys.dm_tran_locks.

HOBT Kilitlenmeye dahil olan bir yığını veya B ağacını temsil eder.
Bu izleme bayrağına özel bir durum yoktur. Bu izleme bayrağına özel bir durum yoktur.

İzleme bayrağı 1204 örneği

İzleme bayrağı 1204 açıldığında aşağıdaki örnek çıkışı gösterir. Bu durumda, Node 1'deki tablo dizin içermeyen bir yığındır ve Node 2'deki tablo, kümelenmemiş dizine sahip bir yığındır. Düğüm 2'deki dizin anahtarı kilitlenme oluştuğunda güncelleştiriliyor.

Deadlock encountered .... Printing deadlock information
Wait-for graph

Node:1

RID: 6:1:20789:0               CleanCnt:3 Mode:X Flags: 0x2
 Grant List 0:
   Owner:0x0315D6A0 Mode: X
     Flg:0x0 Ref:0 Life:02000000 SPID:55 ECID:0 XactLockInfo: 0x04D9E27C
   SPID: 55 ECID: 0 Statement Type: UPDATE Line #: 6
   Input Buf: Language Event:
BEGIN TRANSACTION
   EXEC usp_p2
 Requested By:
   ResType:LockOwner Stype:'OR'Xdes:0x03A3DAD0
     Mode: U SPID:54 BatchID:0 ECID:0 TaskProxy:(0x04976374) Value:0x315d200 Cost:(0/868)

Node:2

KEY: 6:72057594057457664 (350007a4d329) CleanCnt:2 Mode:X Flags: 0x0
 Grant List 0:
   Owner:0x0315D140 Mode: X
     Flg:0x0 Ref:0 Life:02000000 SPID:54 ECID:0 XactLockInfo: 0x03A3DAF4
   SPID: 54 ECID: 0 Statement Type: UPDATE Line #: 6
   Input Buf: Language Event:
     BEGIN TRANSACTION
       EXEC usp_p1
 Requested By:
   ResType:LockOwner Stype:'OR'Xdes:0x04D9E258
     Mode: U SPID:55 BatchID:0 ECID:0 TaskProxy:(0x0475E374) Value:0x315d4a0 Cost:(0/380)

Victim Resource Owner:
 ResType:LockOwner Stype:'OR'Xdes:0x04D9E258
     Mode: U SPID:55 BatchID:0 ECID:0 TaskProxy:(0x0475E374) Value:0x315d4a0 Cost:(0/380)

İzleme bayrağı 1222 örneği

Aşağıdaki örnek, izleme bayrağı 1222 etkin olduğunda çıkan sonucu gösterir. Bu durumda, bir tablo dizin içermeyen bir yığın, diğer tablo ise kümelenmemiş dizine sahip bir yığındır. İkinci tabloda, kilitlenme oluştuğunda dizin anahtarı güncelleştiriliyor.

deadlock-list
 deadlock victim=process689978
  process-list
   process id=process6891f8 taskpriority=0 logused=868
   waitresource=RID: 6:1:20789:0 waittime=1359 ownerId=310444
   transactionname=user_transaction
   lasttranstarted=2022-02-05T11:22:42.733 XDES=0x3a3dad0
   lockMode=U schedulerid=1 kpid=1952 status=suspended spid=54
   sbid=0 ecid=0 priority=0 transcount=2
   lastbatchstarted=2022-02-05T11:22:42.733
   lastbatchcompleted=2022-02-05T11:22:42.733
   clientapp=Microsoft SQL Server Management Studio - Query
   hostname=TEST_SERVER hostpid=2216 loginname=DOMAIN\user
   isolationlevel=read committed (2) xactid=310444 currentdb=6
   lockTimeout=4294967295 clientoption1=671090784 clientoption2=390200
    executionStack
     frame procname=AdventureWorks2022.dbo.usp_p1 line=6 stmtstart=202
     sqlhandle=0x0300060013e6446b027cbb00c69600000100000000000000
     UPDATE T2 SET COL1 = 3 WHERE COL1 = 1;
     frame procname=adhoc line=3 stmtstart=44
     sqlhandle=0x01000600856aa70f503b8104000000000000000000000000
     EXEC usp_p1
    inputbuf
      BEGIN TRANSACTION
       EXEC usp_p1
   process id=process689978 taskpriority=0 logused=380
   waitresource=KEY: 6:72057594057457664 (350007a4d329)
   waittime=5015 ownerId=310462 transactionname=user_transaction
   lasttranstarted=2022-02-05T11:22:44.077 XDES=0x4d9e258 lockMode=U
   schedulerid=1 kpid=3024 status=suspended spid=55 sbid=0 ecid=0
   priority=0 transcount=2 lastbatchstarted=2022-02-05T11:22:44.077
   lastbatchcompleted=2022-02-05T11:22:44.077
   clientapp=Microsoft SQL Server Management Studio - Query
   hostname=TEST_SERVER hostpid=2216 loginname=DOMAIN\user
   isolationlevel=read committed (2) xactid=310462 currentdb=6
   lockTimeout=4294967295 clientoption1=671090784 clientoption2=390200
    executionStack
     frame procname=AdventureWorks2022.dbo.usp_p2 line=6 stmtstart=200
     sqlhandle=0x030006004c0a396c027cbb00c69600000100000000000000
     UPDATE T1 SET COL1 = 4 WHERE COL1 = 1;
     frame procname=adhoc line=3 stmtstart=44
     sqlhandle=0x01000600d688e709b85f8904000000000000000000000000
     EXEC usp_p2
    inputbuf
      BEGIN TRANSACTION
        EXEC usp_p2
  resource-list
   ridlock fileid=1 pageid=20789 dbid=6 objectname=AdventureWorks2022.dbo.T2
   id=lock3136940 mode=X associatedObjectId=72057594057392128
    owner-list
     owner id=process689978 mode=X
    waiter-list
     waiter id=process6891f8 mode=U requestType=wait
   keylock hobtid=72057594057457664 dbid=6 objectname=AdventureWorks2022.dbo.T1
   indexname=nci_T1_COL1 id=lock3136fc0 mode=X
   associatedObjectId=72057594057457664
    owner-list
     owner id=process6891f8 mode=X
    waiter-list
     waiter id=process689978 mode=U requestType=wait

Profilleyici kilitlenme grafiği olayı

SQL Profiler,kilitlenmeye dahil olan görevlerin ve kaynakların grafik gösterimini sunan bir olaya sahiptir. Aşağıdaki örnek, kilitlenme grafı olayı açık olduğunda SQL Profiler'dan alınan çıkışı gösterir.

SQL Profiler ve SQL İzleme özellikleri kullanım dışıdır ve genişletilmiş olaylarla değiştirilir. Genişletilmiş Olaylar daha küçük bir performans yüküne sahiptir ve SQL İzleme'den daha yapılandırılabilir. SQL Profiler'da kilitlenmeleri izlemek yerine Genişletilmiş Olaylar kilitlenme olayını kullanmayı göz önünde bulundurun.

SQL izlemesinden görsel kilitlenme grafiğinin SSMS ekran görüntüsü.

Kilitlenme olayı hakkında daha fazla bilgi için bkz. Lock:Deadlock Event Class. SQL Profiler kilitlenme grafikleri hakkında daha fazla bilgi için bkz. Kilitlenme grafiklerini kaydetme (SQL Server Profiler).

Genişletilmiş Olaylar, SQL İzleme olay sınıflarının eşdeğerlerini sağlar. Daha fazla bilgi için bkz. SQL İzleme Olay Sınıflarına Eşdeğer Genişletilmiş Olayları Görüntüleme. Gelişmiş Olaylar, SQL İzleme yerine önerilir.

Kilitlenmeleri ele alma

Veritabanı Altyapısı örneği kilitlenme kurbanı olarak bir işlem seçtiğinde geçerli toplu işlemi sonlandırır, işlemi geri alır ve uygulamaya 1205 hatasını döndürür. Döndürülen ileti aşağıdaki gibi yapılandırılmıştır:

Your transaction (process ID #...) was deadlocked on {lock | communication buffer | thread} resources with another process and has been chosen as the deadlock victim. Rerun your transaction.

Transact-SQL sorguları gönderen tüm uygulamalar kilitlenme kurbanı olarak seçilebildiği için uygulamaların 1205 hatasını işleyebilen bir hata işleyicisi olmalıdır. Bir uygulama hatayı işlemezse, uygulama işleminin geri alındığını fark etmeyecek şekilde devam edebilir.

Hata 1205'i yakalayan bir hata işleyicisi uygulamak, bir uygulamanın kilitlenmeleri işlemesine ve düzeltme eylemi gerçekleştirmesine olanak tanır (örneğin, kilitlenmeye dahil olan sorguyu otomatik olarak yeniden gönderme).

Uygulamanın sorguyu yeniden göndermeden önce kısa bir süre duraklatılması gerekir. Bu, kilitlenmeye dahil olan diğer işleme, işlemi tamamlama ve kilitlerini serbest bırakma şansı verir. Duraklatma süresinin rastgele olması, yeniden gönderilen sorgu kilitlerini istediğinde kilitlenmenin yeniden oluşması olasılığını en aza indirir. Örneğin, hata işleyicisi bir ile üç saniye arasında rastgele bir süre boyunca duraklatılacak şekilde kodlanabilir.

TRY...CATCH ile işleme

Kilitlenmeleri işlemek için TRY...CATCH kullanabilirsiniz. CATCH bloğu, Hata 1205'i yakalayabilir.

Daha fazla bilgi için bkz. Kilitlenmeleri İşleme.

Kilitlenmeleri en aza indirme

Kilitlenmeleri tamamen önlemek mümkün değildir ancak belirli kodlama kurallarına uygun hareket ederek kilitlenme oluşma olasılığını en aza indirebilirsiniz. Kilitlenmeleri en aza indirmek işlem aktarım hızını artırabilir ve sistem yükünü azaltabilir çünkü daha az işlem:

  • Geri alınır ve işlem tarafından gerçekleştirilen tüm adımlar iptal edilir.
  • Kilitlenme durumunda geri alındıkları için uygulamalar tarafından yeniden gönderilir.

Kilitlenmeleri en aza indirmeye yardımcı olmak için:

  • Nesnelere aynı sırayla erişin.
  • İşlemlerde kullanıcı etkileşimini önleyin.
  • İşlemleri kısa ve tek bir toplu iş içinde tutun.
  • REPEATABLE READ ve SERIALIZABLE gibi daha yüksek yalıtım düzeylerinden, gerekli olmadıklarında kaçının.
  • Satır sürümü tabanlı yalıtım düzeyi kullanın.
    • READ_COMMITTED_SNAPSHOT veritabanı seçeneğini, READ COMMITTED yalıtım düzeyini kullanan işlemler için satır sürümlemeyi kullanmak üzere etkinleştirin.
    • Anlık görüntü yalıtımı işlemlerini kullanın.
  • Bağlı bağlantıları kullanın.

Nesnelere aynı sırada erişme

Tüm eşzamanlı işlemler nesnelere aynı sırada erişiyorsa kilitlenmelerin oluşma olasılığı daha düşüktür. Örneğin, iki eşzamanlı işlem Supplier tablosunda ve ardından Part tablosunda bir kilit alırsa, bir işlem diğer işlem tamamlanana kadar Supplier tablosunda engellenir. İlk işlem başarıyla tamamlandıktan veya geri alındıktan sonra, ikinci işlem devam eder ve bir kilitlenme gerçekleşmez. Tüm veri değişiklikleri için saklı yordamları kullanmak, nesnelere erişim sırasını standartlaştırabilir.

Kilitlenme diyagramı.

İşlemlerde kullanıcı etkileşimlerinden kaçınma

Kullanıcı müdahalesi olmadan çalışan toplu işlemlerin hızı, kullanıcının sorgulara el ile yanıt vermesi gereken hızdan çok daha hızlı olduğundan (örneğin, bir uygulama tarafından istenen parametre istemini yanıtlama) kullanıcı etkileşimi içeren işlemlerden kaçının. İşlem tarafından tutulan tüm kilitler yalnızca işlem gerçekleştirildiğinde veya geri alındığında serbest bırakıldığından bu durum sistem aktarım hızını düşürür. Kilitlenme gerçekleşmese bile, işlemin tamamlanmasını beklerken aynı kaynaklara erişen diğer işlemler engellenir.

İşlemleri kısa ve tek bir toplu işlemde tutma

Kilitlenme genellikle uzun süre çalışan birkaç işlem aynı veritabanında eşzamanlı olarak yürütüldüğünde oluşur. İşlem ne kadar uzun olursa, özel kullanım veya güncelleştirme kilitleri o kadar uzun tutulur, diğer etkinlikler engellenir ve olası kilitlenme durumlarına yol açar.

İşlemlerin tek bir toplu işlemde tutulması, işlem sırasında ağ gidiş dönüşlerini en aza indirir ve istemci işleme nedeniyle işlemin tamamlanmasındaki olası gecikmeleri azaltır.

Daha yüksek yalıtım düzeylerinden kaçının

Bir işlemin daha düşük yalıtım düzeyinde çalıştırılıp çalıştırılamayacağını belirleyin. kullanmak READ COMMITTED , işlemin tamamlanmasını beklemeden başka bir işlem tarafından daha önce okunan (ancak değiştirilmeyen) verileri okumasına olanak tanır. READ COMMITTED gibi SERIALIZABLEdaha yüksek bir yalıtım düzeyinden daha kısa bir süre için paylaşılan kilitleri tutar. Bu, kilit çekişmesini azaltır.

Satır sürümleme tabanlı yalıtım düzeyi kullanmak

READ_COMMITTED_SNAPSHOT Veritabanı seçeneği ayarlandığındaON, yalıtım düzeyi altında READ COMMITTED çalışan bir işlem, okuma işlemleri sırasında paylaşılan kilitler yerine satır sürümü oluşturmayı kullanır.

Tip

Microsoft, bir uygulama kilit tabanlı READ COMMITTED yalıtım düzeyinin engelleme davranışına dayanmadığı sürece, tüm uygulamalar için satır sürümü tabanlı READ COMMITTED yalıtım düzeyini önerir.

Anlık görüntü yalıtımı, okuma işlemleri sırasında paylaşılan kilitleri kullanmayan satır versiyonlama yöntemini de kullanır. Bir işlemin anlık görüntü yalıtımı altında çalışabilmesi için önce veritabanı seçeneğinin ALLOW_SNAPSHOT_ISOLATION ayarlanması ONgerekir.

Okuma ve yazma işlemleri arasında oluşabilecek kilitlenmeleri en aza indirmek için satır sürüm oluşturma tabanlı yalıtım düzeylerini kullanın.

Bağlı bağlantıları kullanma

Bağlı bağlantıları kullanarak, aynı uygulama tarafından açılan iki veya daha fazla bağlantı birbiriyle işbirliği yapabilir. İkincil bağlantılar tarafından alınan tüm kilitler, birincil bağlantı tarafından alınmış gibi tutulur ve tam tersi de geçerlidir. Bu nedenle, birbirlerini engellemezler.

Kilitlenmeye neden olur

Öğrenme veya gösterim amacıyla kilitlenmeye neden olmanız gerekebilir.

Aşağıdaki örnek, AdventureWorksLT2019 varsayılan şema ve verilerle örnek veritabanında çalışır. Bu örneği indirmek için AdventureWorks örnek veritabanları adresini ziyaret edin.

İyileştirilmiş kilitleme etkinleştirildiğinde kilitlenmeye neden olan bir örnek için bkz. İyileştirilmiş kilitleme ve kilitlenmeler.

Kilitlenmeye neden olmak için AdventureWorksLT2019 veritabanına iki oturum bağlamanız gerekir. Bu oturumları Oturum A ve Oturum B olarak adlandırıyoruz. SQL Server Management Studio'da (SSMS) iki sorgu penceresi oluşturarak bu iki oturumu oluşturabilirsiniz.

A Oturumu'nda aşağıdaki toplu işlemi çalıştırın. Bu kod bir açık işlem başlatır ve SalesLT.Product tablosunu güncelleştiren bir deyim yürütür. Bunu yapmak için işlem, tablodaki uygun satırlar üzerinde bir SalesLT.Product alır ve ardından özel (X) kilitlere dönüştürülür. İşlemi açık bırakıyoruz.

BEGIN TRANSACTION;

UPDATE SalesLT.Product
    SET SellEndDate = SellEndDate + 1
WHERE Color = 'Red';

Şimdi, Oturum B'de aşağıdaki toplu işlemi çalıştırın. Bu kod açıkça işlem başlatmaz. Bunun yerine, otomatik komut işlem modunda çalışır. Bu ifade SalesLT.ProductDescription tablosunu günceller. Güncelleştirme, U tablosundaki gerekli satırlarda bir güncelleştirme (SalesLT.ProductDescription) kilidi alır. Sorgu, SalesLT.Product tablosu da dahil olmak üzere diğer tablolara bağlanır.

UPDATE SalesLT.ProductDescription
    SET Description = Description
FROM SalesLT.ProductDescription AS pd
     INNER JOIN SalesLT.ProductModelProductDescription AS pmpd
         ON pd.ProductDescriptionID = pmpd.ProductDescriptionID
     INNER JOIN SalesLT.ProductModel AS pm
         ON pmpd.ProductModelID = pm.ProductModelID
     INNER JOIN SalesLT.Product AS p
         ON pm.ProductModelID = p.ProductModelID
WHERE p.Color = 'Silver';

Bu güncellemeyi tamamlamak için, Oturum B tablodaki satırlarda, S, SalesLT.Product tarafından kilitlenen satırlar da dahil olmak üzere, paylaşılan () kilitlere ihtiyaç duyar. Oturum B, SalesLT.Product üzerinde engellenmiş durumda.

Oturum A'ya dönün. Aşağıdaki UPDATE deyimi çalıştırın. Bu deyim, daha önce açık olan işlemin bir parçası olarak yürütülür.

UPDATE SalesLT.ProductDescription
    SET Description = Description
FROM SalesLT.ProductDescription AS pd
     INNER JOIN SalesLT.ProductModelProductDescription AS pmpd
         ON pd.ProductDescriptionID = pmpd.ProductDescriptionID
     INNER JOIN SalesLT.ProductModel AS pm
         ON pmpd.ProductModelID = pm.ProductModelID
     INNER JOIN SalesLT.Product AS p
         ON pm.ProductModelID = p.ProductModelID
WHERE p.Color = 'Red';

Oturum A'deki ikinci güncelleştirme deyimi, Oturum B tarafından SalesLT.ProductDescriptionüzerinde engellenir.

Oturum A ve Oturum B artık birbirini engelliyor. Her biri diğeri tarafından kilitlenmiş bir kaynağa ihtiyaç duyduğundan hiçbir işlem devam edemez.

Birkaç saniye sonra kilitlenme izleyicisi, Oturum A ve Oturum B işlemlerinin birbirini karşılıklı olarak engellediğini ve bunların hiçbirinin ilerleme kaydedemdiğini belirler. Kilitlenme meydana geldiğini ve Oturum A'nın kilitlenme kurbanı olarak seçildiğini görüyorsunuz. Oturum B başarıyla tamamlandı. A Oturumunun sorgu penceresinde aşağıdaki örneğe benzer bir metin içeren bir hata iletisi görüntülenir:

Msg 1205, Level 13, State 51, Line 7
Transaction (Process ID 51) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

Kilitlenme oluşmamışsa, örnek veritabanınızda READ_COMMITTED_SNAPSHOT özelliğinin etkin olduğunu doğrulayın. Kilitlenmeler herhangi bir veritabanı yapılandırmasında ortaya çıkabilir, ancak bu örnekte etkinleştirilmesi READ_COMMITTED_SNAPSHOT gerekir.

Kilitlenmenin ayrıntılarını SQL Server ve Azure SQL Yönetilen Örneği'nde ring_buffer varsayılan olarak etkin ve etkinleştirilmiş olan olay oturumunun system_health hedefinde görüntüleyebilirsiniz. Aşağıdaki sorguyu göz önünde bulundurun:

WITH cteDeadLocks ([Deadlock_XML])
AS (SELECT CAST (target_data AS XML) AS [Deadlock_XML]
    FROM sys.dm_xe_sessions AS xs
         INNER JOIN sys.dm_xe_session_targets AS xst
             ON xs.[address] = xst.event_session_address
    WHERE xs.[name] = 'system_health'
          AND xst.target_name = 'ring_buffer')
SELECT x.Graph.query('(event/data/value/deadlock)[1]') AS Deadlock_XML,
       x.Graph.value('(event/data/value/deadlock/process-list/process/@lastbatchstarted)[1]', 'datetime2(3)') AS when_occurred,
       DB_Name(x.Graph.value('(event/data/value/deadlock/process-list/process/@currentdb)[1]', 'int')) AS DB --Current database of the first listed process
FROM (SELECT Graph.query('.') AS Graph
      FROM cteDeadLocks AS c
      CROSS APPLY c.[Deadlock_XML].nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS Deadlock_Report(Graph)) AS x
ORDER BY when_occurred DESC;

SSMS'nin içindeki sütunda Deadlock_XML , köprü olarak görünen hücreyi seçerek XML'yi görüntüleyebilirsiniz. Bu çıkışı dosya .xdl olarak kaydedin, kapatın ve ardından görsel kilitlenme grafı .xdl için dosyayı SSMS'de yeniden açın. Kilitlenme grafı aşağıdaki görüntüye benzer olmalıdır.

SSMS'deki bir .xdl dosyasındaki görsel kilitlenme grafiğinin ekran görüntüsü.

İyileştirilmiş kilitleme ve kilitlenmeler

İyileştirilmiş kilitleme ile sayfa ve satır kilitleri işlem sonuna kadar tutulmaz. Satır güncelleştirildiğinde hemen yayımlanırlar. Ayrıca, etkinleştirilirse READ_COMMITTED_SNAPSHOT güncelleştirme (U) kilitleri kullanılmaz. Sonuç olarak kilitlenme olasılığı azalır.

Önceki örnek, güncelleştirme (U) kilitlerine bağlı olduğundan iyileştirilmiş kilitleme etkinleştirildiğinde kilitlenmeye neden olmaz.

Aşağıdaki örnek, en iyi duruma getirilmiş kilitlemenin etkinleştirildiği bir veritabanında kilitlenmeye neden olmak için kullanılabilir.

İlk olarak örnek bir tablo oluşturun ve veri ekleyin.

CREATE TABLE t2
(
    a INT PRIMARY KEY NOT NULL,
    b INT NULL
);

INSERT INTO t2
VALUES (1, 10),
(2, 20),
(3, 30);

İki ayrı oturumda sıralı olarak yürütülen aşağıdaki T-SQL toplu işlemleri bir kilitlenme oluşturur.

Oturum 1'de:

BEGIN TRANSACTION xactA;

UPDATE t2
    SET b = b + 10
WHERE a = 1;

Oturum 2'de:

BEGIN TRANSACTION xactB;

UPDATE t2
    SET b = b + 10
WHERE a = 2;

Oturum 1'de:

UPDATE t2
    SET b = b + 100
WHERE a = 2;

Oturum 2'de:

UPDATE t2
    SET b = b + 20
WHERE a = 1;

Bu durumda, her oturum kendi işlem kimliği (TID) kaynağında özel (X) bir kilit tutar ve diğer TID'de paylaşılan (S) kilidi bekler, bu da bir kilitlenmeye (deadlock) neden olur.

Aşağıdaki kısaltılmış kilitlenme raporu, iyileştirilmiş kilitlemeye özgü öğeleri ve öznitelikleri içerir. Kilitlenme raporundaki <resource-list> her kaynağın altında, her <xactlock> öğe, bir kilitlenmenin her üyesinin temelindeki kaynakları ve TID kilit bilgilerini raporlar.

<deadlock>
 <victim-list>
  <victimProcess id="process12994344c58" />
 </victim-list>
 <process-list>
  <process id="process12994344c58" taskpriority="0" logused="272" waitresource="XACT: 23:2476:0 KEY: 23:72057594049593344 (8194443284a0)" waittime="447" ownerId="3234906" transactionname="xactA" lasttranstarted="2025-10-08T21:36:34.063" XDES="0x12984ba0480" lockMode="S" schedulerid="2" kpid="204928" status="suspended" spid="95" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2025-10-08T21:36:40.857" lastbatchcompleted="2025-10-08T21:36:34.063" lastattention="2025-10-08T21:36:11.340" clientapp="Microsoft SQL Server Management Studio - Query" hostname="WS1" hostpid="23380" loginname="user1" isolationlevel="read committed (2)" xactid="3234906" currentdb="23" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
   <inputbuf>
UPDATE t2
    SET b = b + 20
WHERE a = 1;
   </inputbuf>
  </process>
  <process id="process1299c969828" taskpriority="0" logused="272" waitresource="XACT: 23:2477:0 KEY: 23:72057594049593344 (61a06abd401c)" waittime="3083" ownerId="3234886" transactionname="xactB" lasttranstarted="2025-10-08T21:36:30.303" XDES="0x12995c84480" lockMode="S" schedulerid="2" kpid="63348" status="suspended" spid="88" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2025-10-08T21:36:38.223" lastbatchcompleted="2025-10-08T21:36:30.303" lastattention="1900-01-01T00:00:00.303" clientapp="Microsoft SQL Server Management Studio - Query" hostname="WS1" hostpid="23380" loginname="user1" isolationlevel="read committed (2)" xactid="3234886" currentdb="23" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
   <inputbuf>
UPDATE t2
    SET b = b + 100
WHERE a = 2;
   </inputbuf>
  </process>
 </process-list>
 <resource-list>
  <xactlock xdesIdLow="2476" xdesIdHigh="0" dbid="23" id="lock1299fa06c00" mode="X">
   <UnderlyingResource>
    <keylock hobtid="72057594049593344" dbid="23" objectname="e6fc405e-1ee8-49df-a2b3-54ee0151d851.dbo.t2" indexname="PK__t2__3BD0198ED3CBA65E" />
   </UnderlyingResource>
   <owner-list>
    <owner id="process1299c969828" mode="X" />
   </owner-list>
   <waiter-list>
    <waiter id="process12994344c58" mode="S" requestType="wait" />
   </waiter-list>
  </xactlock>
  <xactlock xdesIdLow="2477" xdesIdHigh="0" dbid="23" id="lock129940b2380" mode="X">
   <UnderlyingResource>
    <keylock hobtid="72057594049593344" dbid="23" objectname="e6fc405e-1ee8-49df-a2b3-54ee0151d851.dbo.t2" indexname="PK__t2__3BD0198ED3CBA65E" />
   </UnderlyingResource>
   <owner-list>
    <owner id="process12994344c58" mode="X" />
   </owner-list>
   <waiter-list>
    <waiter id="process1299c969828" mode="S" requestType="wait" />
   </waiter-list>
  </xactlock>
 </resource-list>
</deadlock>