dataiotech Labs
dbaguidedbaguideDBAdataxtoolsdataopsphere
Home/Hata Teşhis Kütüphanesi/sqlserver-duplicate-key-unique-index
SQL Server
SQL Server 2025 / 2022Veri Bütünlüğü & Kısıtlar
7 dk okuma
Violation of UNIQUE KEY constraint / Cannot insert duplicate key in object

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.

İnceleyen:Senior Database Reliability Engineer
Test Edilen Sürümler: SQL Server 2025 (17.0 CU10 KB5125471) & 2022 (16.0 CU14)

Operasyonel Doğrulama & Güvenilirlik Standardı

Son Teknik İnceleme: 29 Ekim 2026
Test Edilen SürümlerSQL Server 2025 (17.0 CU10 KB5125471) & 2022 (16.0 CU14)
Gerekli YetkiINSERT ve TRY/CATCH blokları çalıştırma yetkisi
Risk Seviyesi
MediumIGNORE_DUP_KEY kullanımı çok satırlı INSERT işlemlerinde hataları sessizce yutarak veri kaybına yol açar
Beklenen ÇıktıEşzamanlı işlemlerde yarış koşulu olmaksızın idempotent kayıt yönetimi
Geri Dönüş (Rollback) Planı:TRY/CATCH rollback veya MERGE sorgusunu standart transaksiyonel kalıba geri alma
Microsoft Learn: SQL Server Unique Indexes & Error 2601/2627
İlk 60 Saniye Teşhis Protokolü:

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

plaintext
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 KoduKaynak NesneAnlamı
Error 2627PRIMARY KEY veya UNIQUE KısıtıTablo seviyesinde tanımlı kısıt ihlali
Error 2601UNIQUE İndeksDoğ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ı:

sql
-- 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:

sql
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 CATCH

Alternatif olarak MERGE kullanılıyorsa mutlaka `WITH (HOLDLOCK)` belirtilmelidir; aksi takdirde MERGE de eşzamanlılık yarışına açıktır:

sql
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

sql
CREATE UNIQUE INDEX IX_Kullanici_Email ON dbo.Kullanici (Email) WITH (IGNORE_DUP_KEY = ON);
DİKKAT / TEHLİKE
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ı

sql
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öster

Gerektiğinde DBCC CHECKIDENT ('dbo.Kullanici', RESEED, <max_id>) ile identity sayacı hizalanabilir.

Diğer Veritabanı Hata Teşhisleri

Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.

Tüm Hatalar (50)