SQL Server "Cannot insert duplicate key row" — 2601 mi, 2627 mi?
2601 ile 2627 arasındaki fark, yarış koşulu kaynaklı tekrarlar, idempotent yazma deseni ve IGNORE_DUP_KEY'in neden tehlikeli olduğu.
Operasyonel Doğrulama & Güvenilirlik Standardı
Hata mesajı semptomdur, kök neden değildir. Sunucuyu yeniden başlatmadan veya rastgele ayar değiştirmeden önce aşağıdaki "Nedeni ayırt eden tek sorgu"yu çalıştırarak gerçek senaryoyu netleştirin.
▸Belirti
Violation of UNIQUE KEY constraint 'UQ_Kullanici_Email'.
Cannot insert duplicate key in object 'dbo.Kullanici'. The duplicate key value is (a@b.com).İki hata numarası arasındaki ayrım teşhis için kritiktir:
| Hata Kodu | Kaynak Nesne | Anlamı |
|---|---|---|
| Error 2627 | PRIMARY KEY veya UNIQUE Kısıtı | Tablo seviyesinde tanımlı kısıt ihlali |
| Error 2601 | UNIQUE İndeks | Doğrudan oluşturulmuş tekil indeks ihlali |
▸En Sık Neden: Yarış Koşulu (Race Condition)
Uygulama kodlarında sıkça yapılan desen hatası:
-- YANLIŞ DESEN: Kontrol ile yazma arasında yarış boşluğu vardır
IF NOT EXISTS (SELECT 1 FROM dbo.Kullanici WHERE Email = @e)
INSERT INTO dbo.Kullanici (Email) VALUES (@e);İki eşzamanlı istek aynı anda IF NOT EXISTS kontrolünden geçer ve ikisi de INSERT komutunu çalıştırarak birinin 2601/2627 almasına yol açar.
▸Doğru Çözüm: Idempotent Hata Yakalama
Veritabanının kendi ACID tekillik garantisinden yararlanın:
BEGIN TRY
INSERT INTO dbo.Kullanici (Email, Ad) VALUES (@e, @ad);
END TRY
BEGIN CATCH
IF ERROR_NUMBER() IN (2601, 2627)
-- Kayıt zaten var: Mevcut kaydı oku ve devam et
SELECT * FROM dbo.Kullanici WHERE Email = @e;
ELSE
THROW;
END CATCHAlternatif olarak MERGE kullanılıyorsa mutlaka `WITH (HOLDLOCK)` belirtilmelidir; aksi takdirde MERGE de eşzamanlılık yarışına açıktır:
MERGE dbo.Kullanici WITH (HOLDLOCK) AS h
USING (SELECT @e AS Email) AS s ON h.Email = s.Email
WHEN NOT MATCHED THEN INSERT (Email) VALUES (s.Email);▸Tehlikeli Kısayol: IGNORE_DUP_KEY
CREATE UNIQUE INDEX IX_Kullanici_Email ON dbo.Kullanici (Email)
WITH (IGNORE_DUP_KEY = ON);IGNORE_DUP_KEY = ON tekrarlanan satırları sessizce atlar ve sadece uyarı verir. Uygulama satırın başarıyla eklendiğini varsayar ancak veritabanına yazılmamıştır; çok satırlı INSERT işlemlerinde hangi verilerin kaybolduğunu takip etmek imkansız hale gelir. Üretim ortamlarında önerilmez.▸Tekrar Eden Diğer Neden: IDENTITY Kayması
SELECT OBJECT_NAME(object_id) AS tablo, is_identity
FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.Kullanici') AND is_identity = 1;
DBCC CHECKIDENT ('dbo.Kullanici', NORESEED); -- Mevcut değeri gösterGerektiğinde DBCC CHECKIDENT ('dbo.Kullanici', RESEED, <max_id>) ile identity sayacı hizalanabilir.
- •Kardeş Hata (PostgreSQL): PostgreSQL duplicate key violates unique constraint (Sequence kayması)
- •İlgili Hata: SQL Server Error 547: Foreign Key Constraint
- •Veritabanı Hub: SQL Server Üretim Mimarisi Rehberi
Diğer Veritabanı Hata Teşhisleri
Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.
SQL Server Error 18456: State Kodlarına Göre Gerçek Neden
18456 hatasında State numarası gerçek nedeni söyler. State 5, 8, 11, 18, 38 ve 40 için ayrı çözümler, ERRORLOG okuma komutları.
SQL Server Error 1205 Deadlock: Grafiği Bulma ve Önleme
SQL Server 1205 hatasında deadlock grafiğini system_health oturumundan çıkarma, kurban seçimini anlama ve kalıcı önleme yöntemleri.
SQL Server Pool Timeout: Bağlantı Havuzu Tükenmesi Çözümü
"Timeout expired prior to obtaining a connection from the pool" hatasının komut zaman aşımından farkı, sızıntı tespiti ve .NET tarafında kalıcı düzeltme.