Çözülmesi kolay birkaç olası senaryo ve olmayan zararlı bir senaryo var.
Bir değer girip bir süre sonra aynı değeri giren bir kullanıcı için INSERT sorunu algılayamadan önce basit bir SELECT (SEÇ) seçeneğini seçin. Bu, bir kullanıcının bir değer göndermesi ve bir süre sonra başka bir kullanıcının aynı değeri göndermesi durumunda işe yarar.
Kullanıcı, kodun tek bir çağrısında yinelenen değerlerin bir listesini gönderirse (örneğin, {ABC, DEF, ABC}), uygulama yinelenenleri algılayıp filtreleyebilir, belki de bir hata atar. Eklemeden önce DB'nin benzersiz değerlerden herhangi birini içermediğini de kontrol etmeniz gerekir.
Zor senaryo, bir kullanıcının yazma işlemi başka bir kullanıcının yazma işlemi ile aynı anda DBMS'nin içindeyse ve aynı değeri yazmasıdır. Sonra aralarında bir koşul var. DBMS (büyük olasılıkla - hangisini kullandığınızı söylemezsiniz) önleyici çoklu görev sistemi olduğundan, herhangi bir görev yürütmenin herhangi bir noktasında duraklatılabilir. Bu, user1'in görevinin mevcut bir satır olmadığını kontrol edebileceği anlamına gelir, daha sonra user2'nin görevi mevcut bir satır olmadığını kontrol edebilir, daha sonra user1'in görevi bu satırı ekleyebilir, daha sonra user2'nin görevi bu satırı ekleyebilir. Her noktada görevler bireysel olarak mutlu ve doğru olanı yapıyorlar. Ancak genel olarak bir hata oluşur.
Genellikle bir DBMS, söz konusu değere bir kilit koyarak bunu ele alır. Bu problemde yeni bir satır oluşturuyorsunuz, böylece kilitlenecek bir şey yok. Cevap bir aralık kilidi. Önerdiği gibi, şu anda var olsun ya da olmasın, bir dizi değeri kilitler. Bir kez kilitlendikten sonra, kilit bırakılana kadar bu aralığa başka bir görev tarafından erişilemez. Aralık kilitleri almak için SERİLEŞTİRİLEBİLİR yalıtım seviyesini belirlemeniz gerekir . Göreviniz kontrol edildikten sonra üst üste gizlice girme olgusu hayali kayıtlar olarak bilinir .
İzolasyon seviyesini tüm uygulama boyunca Seri hale getirilebilir olarak ayarlamanın sonuçları olacaktır. Üretilen olacaktır azaltılabilir. Geçmişte yeterince iyi çalışan diğer yarış koşulları şimdi hata göstermeye başlayabilir. Yinelenen kodunuzu yürüten ve uygulamanın geri kalanını olduğu gibi bırakan bağlantıya ayarlamanızı öneririm.
Kod tabanlı bir alternatif, yazmadan sonra öncekine göre kontrol etmektir. Öyleyse INSERT yapın, ardından bu karma değerine sahip satır sayısını sayın. Yinelenen işlemler varsa geri alın. Bunun sapkın sonuçları olabilir. Diyelim ki görev 1 yazıyor, sonra görev 2. Sonra görev 1 yineleniyor. İlk olmasına rağmen geri döner. Benzer şekilde, her iki görev de yinelenen ve her iki geri dönüşü algılayabilir. Ancak en azından çalışmak için bir mesajınız olacak, bir yeniden deneme mekanizması olacak ve yeni kopyalar olmayacak. Program akışını kontrol etmek için istisnalar kullanmak gibi, geri almalar kaşlarını çattı. Not iyi ki hepsiişlemde sadece yinelenen yazma yazma değil, geri alınır. Ve eşzamanlılığı azaltabilecek açık işlemlere sahip olmanız gerekir. Karma üzerinde bir dizin yoksa, yinelenen denetim korkunç yavaş olacaktır. Bunu yaparsanız, onu benzersiz bir hale getirebilirsiniz!
Yorumladığınız gibi, gerçek çözüm benzersiz bir indekstir. Bana öyle geliyor ki bu bakım pencerenize sığmalıdır (tabii ki sisteminizi en iyi biliyorsunuz). Diyelim ki karma sekiz bayt. Yüz milyon sıra için yaklaşık 1GB. Deneyim, makul bir donanımın bu birçok satırı bir veya iki dakika içinde işleyeceğini gösteriyor. Yinelenen kontrol ve eleme buna eklenir, ancak önceden yazılabilir. Yine de bu bir yana.