Tablock ipucu çıkmazları tetikler


10

Aşağıdaki formun SQL ile paralel ve SQL ile çalışan iki Execute SQL Görevleri kullanarak boş bir yığın tabloya en az günlük kaydı kullanarak iki veri kümesi ekliyordu.

INSERT INTO Table (TABLOCK) SELECT FROM ...

İş biraz askıda kaldıktan sonra, SQL görevlerinden biri çıkmaz kurban oldu. Kilitlenme grafiğinin XML çıktısı aşağıdadır.

Birisi kaputun altında neler olduğunu açıklayabilir mi?

  <resource-list>
   <objectlock lockPartition="0" objid="1586156746" subresource="FULL" dbid="7" objectname="dbo.TargetTable" id="lock7374a00" mode="IX" associatedObjectId="1586156746">
    <owner-list>
     <owner id="process9609dc8" mode="Sch-S"/>
     <owner id="process9609dc8" mode="IX"/>
    </owner-list>
    <waiter-list>
     <waiter id="process5e13048" mode="X" requestType="convert"/>
    </waiter-list>
   </objectlock>
   <objectlock lockPartition="0" objid="1586156746" subresource="FULL" dbid="7" objectname="dbo.TargetTable" id="lock7374a00" mode="IX" associatedObjectId="1586156746">
    <owner-list>
     <owner id="process5e13048" mode="Sch-S"/>
     <owner id="process5e13048" mode="IX"/>
    </owner-list>
    <waiter-list>
     <waiter id="process9609dc8" mode="X" requestType="convert"/>
    </waiter-list>
   </objectlock>
  </resource-list>

Çoğu durumda iki Execute SQL Görevinin başarılı bir şekilde paralel çalışabileceğini bulduğum için işler çok daha karmaşıklaşıyor. Aşağıdan deneyin:

Create table dbo.TablockInsert (c1 int, c2 int, c3 int)

--then issue the script in two Execute Sql Task in parallel you won't fail:
insert into dbo.TablockInsert(TABLOCK) SELECT 1, 1, 1

Tek fark SELECT ... FROM ... ifadesi olduğundan, SELECT ... FROM ... ifadesinin burada kilit modu üzerinde bir etkisi olabilir mi?


Kilitlenmeyi önlemek için TABLOCK yerine TABLOCKX belirtebilirsiniz. Bu da tabloya erişimi seri hale getirse de, yine de minimum günlük kaydı elde edersiniz.
Dan Guzman

Yanıtlar:


8

Veri Yükleme Performansı Kılavuzu SQL Server 2008 için yazılmıştır ama çok anlarım gibi Microsoft yığınları için bu alanın gelişimini vermiş değil. Yükleme senaryonuz için bir teklif:

Boş, Bölümlenmemiş Bir Tabloyu Toplu Yükleme

Bölümlenmemiş bir tabloya veri yüklemek, basit bir işlem olmakla birlikte, çeşitli şekillerde optimize edilebilir.

...

Yığınlar için birden çok eşzamanlı ekleme işlemi, yalnızca seçilen toplu yöntem tablo üzerinde toplu güncelleme (BU) kilitleri verdiğinde mümkündür. İki toplu güncelleme (BU) kilidi uyumludur ve bu nedenle iki toplu işlem aynı anda çalışabilir.

Bu senaryoda, INSERT… SELECT ve SELECT INTO'un bir dezavantajı vardır. Bu işlemlerin her ikisi de hedefe özel (X), masa seviyesi kilidi alır. Bu, belirli bir zamanda yalnızca bir dökme yük işleminin çalıştırılabileceği ve ölçeklenebilirliği sınırlayacağı anlamına gelir. Ancak, BCP, BULK INSERT ve Integration Services, toplu güncelleme (BU) kilitlerini alabilir - TABLOCK ipucunu belirtirseniz.

Önemli olan, bir BU kilit almamanızdır INSERT ... SELECT. Masada her zaman özel bir kilit elde edersiniz, böylece bir INSERTseferde sadece bir tane çalışabilir.

Yorumlarda, 100 bin veya daha az satır ekleyeceğinizi ve ekler sırasında tablolarda diğer işlemlerin çalışmadığını söylemiştiniz. Veritabanına iki INSERT sorgusu gönderirken üç şeyden birinin olmasını beklerim:

  1. Bir kesici uç önce çalışır ve diğer kesici uç engellenir. İkinci kesici uç, birinci kesici uç tamamlanana kadar bekler.
  2. Bir kesici uç, ikinci kesici uç başlamadan önce biter. Açık bir engelleme yoktur, ancak aynı anda çalıştırılmazlar.
  3. Bir kilitlenme elde edersiniz ve yalnızca bir ek başarıyla tamamlanır.

Her durumda TABLOCKX, sorguya bir ipucu ekleyerek yararlanırsınız ya da zarar görmezsiniz , bu yüzden kilitlenmeyle ilgili tavsiyem budur. Kilitlenmenin neden bazen gerçekleştiğini bilmek istiyorsanız, bunun için başka bir cevaba bakmanız gerekir.

Paralel eklemeye gerçekten ihtiyaç duyduğunuz farklı bir senaryoda, BU sorununun etrafında çalışmanın iki yolu, yığınınızı bölümlemek ve her oturumun ayrı bir bölüme eklenmesini sağlamak veya verilerinizi BCP, BULK INSERT veya Integration Services aracılığıyla yüklemektir. .


Cevabınız için teşekkürler, ancak şimdiye kadar yaşadığım tek kilitlenme durumuyla karşılaştım. Çoğu durumda paralel olarak (TABLOCK) SELECT FROM İLE EKLEME yaptığınızda, iş başarısız olmaz. BTW, SQL SERVER 2008 R2 kullanıyorum. Soruma başarılı bir örnek ekledim.
SqlWhale

@tec, muhtemelen başarısız olmadığı durumlarda seri olarak çalışırlar. Belki de sadece plan derleme için belirli bir başlangıç ​​zamanı olduğunda sorunla karşılaşırsınız.
Martin Smith

@MartinSmith Projede sorunla karşılaştığım sorgu SELECT 1 örneğinden çok daha karmaşık, bu da daha fazla derleme yükü gerektiriyor, ancak sadece birkaç tablodan okuyor. Daha karmaşık sorgular tarafından bu tür çıkmazı yeniden oluşturmaya çalışıyorum.
SqlWhale

@TecKnowNothing Kaç satır eklediğiniz hakkında? Süreç günde kaç kez çalışır? Veri yüklenirken başka sorgular tablodan SEÇİLİR mi?
Joe Obbish

@JoeObbish 1. Burada satırların sayısı sorun olduğunu düşünmüyorum, sadece her sorgu için 4000 - 70000 var ve bunlar küp kullanımı için son derece toplanmış verilerdir. 2. Günde bir kez çalışması gereken test aşamasında. Hedef tablodan başka bir şey okumuyor.
SqlWhale

4

Sen içine yerleştirdikten olan dbo.TargetTableiki toplantıdan ve ikisini de kullanarak TABLOCKhint.Both process9609dc8ve process5e13048süreç holdingi Sch-Sve IXhem süreç aynı anda tutabilir böylece birbiriyle uyumlu kilitler. Ancak her ikisi de IXkilidi Exclusive Xtüre dönüştürmek istiyor . Xkilitler birbiriyle uyumlu değildir. Bu nedenle, SQL sunucusu oturumu birini sonsuza kadar birbirini beklemek yerine kilitlenme kurbanı olarak seçti.

Temel kilitlenme bilgileri.

Kilit Uyumluluğu (Veritabanı Altyapısı) grafiği.

Kilitlenmeleri Algılama ve Sonlandırma.

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.