TL; DR: Aşağıdaki soru aşağı doğru kayıyor: Bir satır eklerken , bir dış gözlemcinin daha yeni görebileceği kümelenmiş dizindeki yeni bir değerin üretilmesi ve karşılık gelen satır anahtarının kilitlenmesi arasında bir fırsat penceresi var mı? eşzamanlı bir işlem tarafından eklenen değer? (SQL Server'da.)Identity
Identity
Detaylı versiyon
Tablonun kümelenmiş indeksinin anahtarı olan (ayrıca birkaç kümelenmemiş ek dizini olan) bir Identity
sütunu olan bir SQL Server masam var CheckpointSequence
. Satırlar tabloya birkaç eşzamanlı işlem ve iş parçacığı (izolasyon düzeyinde ve olmadan ) eklenir . Aynı zamanda, kümelenmiş dizinden, o sütuna göre sıralanan (aynı zamanda izolasyon düzeyinde , seçenek kapatılmış olarak) satırları düzenli olarak okuyan işlemler vardır .READ COMMITTED
IDENTITY_INSERT
CheckpointSequence
READ COMMITTED
READ COMMITTED SNAPSHOT
Şu anda okuma işlemlerinin bir kontrol noktasını asla atlayamayacağı gerçeğine güveniyorum. Sorum şu: Bu mülke güvenebilir miyim? Olmazsa doğrulamak için ne yapabilirim?
Örnek: kimlik değerlerinin olan satırlar 1, 2, 3, 4, ve 5 sokulur, okuyucu zaman olmamalıdır , önceki değerine sahip bir görme değerin 5 ile satır bkz 4. testler gösteriyor ki, bir içeren bir sorgu, ORDER BY CheckpointSequence
madde ( ve bir WHERE CheckpointSequence > -1
cümle), 4. satırın ne zaman okunacağını, ancak henüz 5. satırın daha önce gerçekleştirilmiş olmasına rağmen henüz taahhüt edilmediğini güvenilir bir şekilde engeller.
En azından teoride, bu varsayımın bozulmasına neden olabilecek bir yarış durumu olabileceğine inanıyorum. Maalesef, belgelendirme birden fazla eşzamanlı işlem bağlamında Identity
nasıl Identity
çalıştığı hakkında pek fazla bir şey ifade etmiyor , sadece “Her yeni değer mevcut tohum ve artışa göre üretiliyor” diyor. ve "Belirli bir işlem için her yeni değer, tablodaki eşzamanlı diğer işlemlerden farklıdır." ( MSDN )
Benim akıl yürütme, bir şekilde bu şekilde çalışması gerekir:
- Bir işlem başlatıldı (açıkça veya dolaylı olarak).
- Bir kimlik değeri (X) üretilir.
- İlgili satır kilidi, kimlik değerine bağlı olarak kümelenmiş endekste alınır (kilit yükseltme başlamazsa, bu durumda tüm tablo kilitlenir).
- Satır eklenir.
- İşlem gerçekleştirilir (çok uzun zaman sonra), bu nedenle kilit tekrar kaldırılır.
Bence 2. ve 3. adımlar arasında, çok küçük bir pencere var.
- eşzamanlı bir oturum sonraki kimlik değerini (X + 1) üretebilir ve kalan tüm adımları uygulayabilir,
- Böylece bir okuyucunun X + 1 değerini okuması için tam olarak bu noktada gelmesi, X'in değerini kaybetmesi.
Tabii ki, bunun olasılığı son derece düşük görünüyor; ama yine de - olabilirdi. Veya olabilir mi?
(Bağlamla ilgileniyorsanız: Bu, NEventStore'un SQL Kalıcılık Motorunun bir uygulamasıdır. NEventStore, her olayın yeni, artan bir denetim noktası sıra numarası aldığı bir yalnızca salt okunur olay deposu uygular. Müşteriler, kontrol noktası tarafından sipariş edilen olay mağazasından olayları okurlar. Her türlü hesaplamaları yapabilmek için, X kontrol noktası olan bir olay işlendikten sonra, müşteriler sadece "yeni" olayları, yani X + 1 ve üstü kontrol noktası olan olayları göz önünde bulundururlar.Bu nedenle, olayların hiçbir zaman atlanmaması çok önemlidir. . onlar daha göz önünde asla gibi ben şu anda olmadığını belirlemek için çalışıyorum Identity
. tabanlı kontrol noktası uygulaması bu gereksinimi karşılar Bunlar kullanılan tam SQL ifadeleri : Şema , Yazarlar sorgu ,Okuyucunun Sorgusu .)
Eğer haklıysam ve yukarıda açıklanan durum ortaya çıkarsa, her ikisi de tatmin edici olmayan, onlarla başa çıkmak için yalnızca iki seçenek görebilirim:
- X'i görmeden önce X + 1 değerinde bir kontrol noktası sırası görünce, X + 1'i kapatın ve daha sonra tekrar deneyin. Bununla birlikte,
Identity
elbette boşluk üretebileceğinden (örneğin, işlem geri alındığında), X asla gelmeyebilir. - Yani, aynı yaklaşım, ancak n milisaniyeden sonra boşluğu kabul edin. Bununla birlikte, n'nin değerini kabul etmeliyim?
Daha iyi bir fikrin var mı?