dataiotech Labs
dbaguidedbaguideDBAdataxtoolsdataopsphere
Home/PostgreSQL/Hata Kodları (Errors)/postgresql-duplicate-key-sequence
[Teşhis]PostgreSQL PG 14 - 17Intermediate
4 dk okuma

PostgreSQL duplicate key Hatası: Sequence Kayması Düzeltme

PostgreSQL "duplicate key value violates unique constraint" — Sequence Neden Geride Kalır?

Yazar / Standart:Kıdemli Veritabanı Mimarı & SRE (dataiotech Labs)
duplicate key value violates unique constraint "kullanicilar_pkey"
İ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
ERROR: duplicate key value violates unique constraint "kullanicilar_pkey" DETAIL: Key (id)=(1043) already exists.

Bu hatanın ayırt edici işareti şudur: tabloda `id = 1043` olan bir kayıt zaten var, ama `INSERT` bu değeri üretmeye çalışıyor. Genellikle şu üç durumdan sonra ortaya çıkar:

  • •Veritabanı geri yüklendi (pg_restore, psql < dump)
  • •Veriler başka bir sistemden, açık id değerleriyle içe aktarıldı
  • •Tablo yeniden oluşturuldu ve veriler kopyalandı

pg_dump sequence durumunu dump anındaki haliyle yazar. Sonradan açık id ile eklenen satırlar sequence'ı ilerletmez.


▸Doğrulama

sql
SELECT max(id) AS tablodaki_en_buyuk FROM kullanicilar; SELECT last_value, is_called FROM kullanicilar_id_seq;

tablodaki_en_buyuk > last_value ise tanı kesindir.


▸Çözüm

1. Tek tablo için hızlı onarım:

sql
SELECT setval( pg_get_serial_sequence('public.kullanicilar', 'id'), (SELECT max(id) FROM public.kullanicilar) );

2. Tüm şemayı tarayan otomatik DO bloğu: Restore sonrası tek tek uğraşmak yerine:

sql
DO $$ DECLARE r record; m bigint; BEGIN FOR r IN SELECT n.nspname AS sch, c.relname AS tab, a.attname AS col, pg_get_serial_sequence( quote_ident(n.nspname) || '.' || quote_ident(c.relname), a.attname ) AS seq FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum > 0 WHERE c.relkind = 'r' AND n.nspname NOT IN ('pg_catalog', 'information_schema') LOOP CONTINUE WHEN r.seq IS NULL; EXECUTE format('SELECT max(%I) FROM %I.%I', r.col, r.sch, r.tab) INTO m; IF m IS NOT NULL THEN PERFORM setval(r.seq, m); RAISE NOTICE '% => %', r.seq, m; END IF; END LOOP; END $$;

▸İlgili Mühendislik Rehberleri ve İç Linkler

PostgreSQL Diğer Üretim Rehberleri

Aynı veritabanı motoruna ait doğrulanmış diğer içerikler.

Tümünü Gör