SORU
26 Mart 2010, Cuma


SQL atom UPSERT 2005 Server

Bir atom yapmak için doğru düzeni "" (EKLE aksi halde bulunduğu UPDATE) SQL Server 2005? UPSERT nedir

İki parçalı desene ile bir sürü kod üzerinde (örneğin http://stackoverflow.com/questions/639854/tsql-check-if-a-row-exists-otherwise-insert) görüyorum

UPDATE ...
FROM ...
WHERE <condition>
-- race condition risk here
IF @@ROWCOUNT = 0
  INSERT ...

ya

IF (SELECT COUNT(*) FROM ... WHERE <condition>) = 0
  -- race condition risk here
  INSERT ...
ELSE
  UPDATE ...

nerede < durum >doğal anahtarları bir değerlendirme olacaktır. Yukarıdaki yaklaşımların hiçbiri iyi eşzamanlılık ile anlaşma gibi görünüyor. Eğer aynı doğal tuşu ile iki satır veremem, yukarıdaki risk tüm yarış durumu senaryolarda aynı doğal tuşu ile satır ekleme gibi görünüyor.

Aşağıdaki yöntemi kullanıyorum ama sorunun ne olduğunu merak ediyordum bu yüzden insanların tepkileri her yerde görmek beni pek şaşırtmadı

INSERT INTO <table>
SELECT <natural keys>, <other stuff...>
FROM <table>
WHERE NOT EXISTS
   -- race condition risk here?
   ( SELECT 1 FROM <table> WHERE <natural keys> )

UPDATE ...
WHERE <natural keys>

Yarış durumu burada daha önce belirtildiği kodu olanlardan farklı olduğunu unutmayın. Önceki kodda sorun okur (satır başka bir oturum tarafından SEÇİN EKLE/arasında/veya yayınlanması arasında eklenen) hayalet oldu. Yukarıdaki kodu, yarış durumu Siler. Eşleşen bir Satır EKLE yürütür önce (BURADA VAR) çalıştırdıktan SONRA ancak başka bir oturum tarafından silinmiş olması mümkün müdür? NEREDE bu GÜNCELLEME ile birlikte bir şey üzerinde bir kilit koyar MEVCUT olmadığı belli değil.

Bu atom? Bu SQL Server belgelerinde belirtildiği olacağı bulamıyorum.

DÜZENLEME:Bu işlemler ile yapılabilir biliyorum, ama işlem düzeyi hayalet okuma sorunu önlemek için seri hale getirilebilir ayarlamak gerek diye düşünüyorum? Kesinlikle böyle ortak bir sorun için abartılı olur?

CEVAP
26 Mart 2010, Cuma


INSERT INTO <table>
SELECT <natural keys>, <other stuff...>
FROM <table>
WHERE NOT EXISTS
   -- race condition risk here?
   ( SELECT 1 FROM <table> WHERE <natural keys> )

UPDATE ...
WHERE <natural keys>
  • ilk EKLEME bir yarış durumu var. Anahtar iç sorgusu sırasında var, ama EKLEMEK zaman anahtar ihlali sonucu yıkılmıştır olmayabilir.
  • EKLEME ve GÜNCELLEME arasında bir yarış durumu vardır. Anahtar EKLE iç sorguda işaretlendiğinde olabilir ama zaman GÜNCELLEME çalışır oldu.

İkinci yarış için durumu bir anahtar gerçekten kayıp bir güncelleme değil neyse eşzamanlı iş parçacığı tarafından silinmiş, olurdu da söylenebilir.

En iyi çözüm genellikle büyük olasılıkla denemek ve eğer başarısız olursa hata işleme (tabi bir işlem içinde):

  • eğer anahtarı kayıp olasılığı varsa, her zaman ilk yerleştirin. Benzersiz kısıtlama ihlali, güncelleme için geri dönüş kolu.
  • eğer anahtarı ihtimali varsa, her zaman ilk güncelleme. Hiçbir Satır Ekle bulundu. Olası benzersiz kısıtlama ihlali, güncelleme için geri dönüş kolu.

Doğruluğu ayrıca, bu model de hız için idealdir: daha verimli sahte kilitlenmelerine. yapacak daha eklemek ve bu özel durumu işlemek için çalışmaktır Kilitlenmelerine mantıksal sayfa okur yani fiziksel sayfa okur anlamına gelebilir () ve IO (bile) mantıklı SEH daha pahalı.

Güncelleme@Peter

Neden tek bir açıklama değil 'atom'? Hadi önemsiz bir tablo var ki:

create table Test (id int primary key);

Şimdi Eğer bir döngü içinde iki iş parçacığı bu tek deyimi çalıştırın olsaydım olurdu 'atom' dediğiniz gibi, hiç bir yarış durumu var

  insert into Test (id)
    select top (1) id
    from Numbers n
    where not exists (select id from Test where id = n.id); 

Henüz yalnızca birkaç saniye içinde, bir birincil anahtar ihlali oluşur:

2627, Düzey 14, 1, 4 Satır Devlet Msg
BİRİNCİL ANAHTAR kısıtlaması ihlali 'PK_Test'. _24927208 Yinelenen anahtar nesne eklenemiyor 'dbo.'. Test

Bu yüzden mi? SQL sorgu planı 'doğru olanı' birçok diğer durumlarda WITH cte AS (SELECT...FROM ) DELETE FROM cte DELETE ... FROM ... JOIN ve. bu doğru Ama bu gibi durumlarda çok önemli bir fark var: 'sorgu' anlamına gelirhedefbirgüncellemeyasiloperasyon. Bu gibi durumlar için sorgu planı gerçekten uygun bir kilit kullanır, aslında ben bu davranış gibi uygulama sıraları Using tables as Queues bazı durumlarda, önemlidir.

Ama asıl soru, benim örnekte, alt sorgu görmediğinden sorgu iyileştiricisi gibi bir sorgu içinde sorgu, bazı özel tarama için güncelleme' türünü sorgulamak gerekiyor özel kilit koruması. Sonuç sorgu yürütme aramaconcurent bir observerver tarafından ayrı bir işlem olarak görülebilirböylece kırma 'atom' deyiminin davranış. Özel önlem alınmadığı takdirde, birden çok iş parçacığı aynı değeri eklemek, kontrol ettiler, hem de ikna için deneyebilirsiniz ve değeri zaten yok. Biri başarılı, diğeri PK ihlali vuracaktır. QED.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • ItZWaffleS420

    ItZWaffleS42

    9 EYLÜL 2011
  • Rooster Teeth

    Rooster Teet

    11 Temmuz 2006
  • rtisticsdev

    rtisticsdev

    31 Mayıs 2012