· kaynak dev.to (home feed)
PostgreSQL 19'da sequence replikasyonu yalnızca açık refresh ile ilerliyor, promote sırasında ID çakışması riski doğuruyor
PostgreSQL 19 RC1 üzerinde yapılan uygulamalı testler, subscriber'daki sequence'ların yalnızca snapshot anlarında senkronize olduğunu gösteriyor; bu yüzden son bir refresh yapılmadan subscriber'ı promote etmek yinelenen anahtar (duplicate-key) ID çakışmalarına yol açabiliyor.

Sequence replikasyonu PostgreSQL 19'a geliyor
PostgreSQL 19'nun release candidate sürümü, bir publication'ın ALL SEQUENCES tanımlamasına izin veriyor ve bu publication'dan oluşturulan bir subscriber, ilk tablo senkronizasyonunun parçası olarak publisher'daki güncel sequence pozisyonlarını içe aktarıyor. Bunun yanında iki destekleyici parça daha geliyor: talep üzerine güncel değerleri çeken ALTER SUBSCRIPTION ... REFRESH SEQUENCES komutu ve bir subscriber'ın bir sequence'a şu an ne değer atadığını incelemek için kullanılan yeni pg_get_sequence_data() fonksiyonu. dev.to'da yayınlanan uygulamalı bir yazıya göre bunların hiçbiri PostgreSQL 18'de bulunmuyor; bu sürümde eşdeğer CREATE PUBLICATION ifadesi basitçe bir sözdizimi hatasıyla başarısız oluyor.
Hedeflenen failover sorunu
Tarihsel olarak logical replication tablo satırlarını kopyalarken sequence'ları tamamen yok sayıyordu. Bu yüzden bir arıza sonrasında primary olarak promote edilen bir subscriber, hâlâ varsayılan başlangıç konumunda duran bir sequence'dan ID dağıtıyordu ve ilk yerel insert'ler diskte zaten mevcut olan satırlarla çakışıyordu. Yazarın da belirttiği gibi, bu davranış ekiplerin major sürüm yükseltmeleri veya olağanüstü durum kurtarma (disaster recovery) için logical replication'dan kaçınmasının ve bunun yerine fiziksel replikasyonu kullanmasının standart nedenlerinden biri; oysa fiziksel replikasyon hangi tabloların geçeceğini filtreleyemiyor.
Bir stream değil, snapshot
Testlerde paylaşımlı bir Docker ağında iki postgres:19rc1 container'ı çalıştırıldı; publisher tarafında wal_level logical olarak ayarlandı, bigint identity primary key'e sahip bir tablo ve 1.000 satır tohum verisi kullanıldı. İlk senkronizasyondan sonra hem PostgreSQL 18 hem PostgreSQL 19 subscriber 1.000 satırın tamamına sahipti, ancak sequence'lar ayrıştı: 19 subscriber'daki orders_id_seq 1.000'e ulaşırken 18 subscriber'daki hiç 1'den kımıldamadı. 18 subscriber'a az önce promote edilmiş gibi insert çalıştırıldığında, id 1 üzerindeki yinelenen anahtar ihlali nedeniyle anında başarısız oldu; taze 19 subscriber'daki aynı insert ise id 1001 döndürdü ve başarılı oldu.
Sınırlama, yazar subscription'a dokunmadan publisher üzerinden 500 satır daha iterken ortaya çıktı. Subscriber'ın tablo verisi tamamen yetişti; hem count(*) hem max(id) 1.500'e ulaştı, ama sequence 1.000'de kaldı. Başka bir deyişle, PostgreSQL 19'daki sequence senkronizasyonu satır değişiklikleriyle birlikte sürekli akan bir stream değil, belirli anlarda — CREATE SUBSCRIPTION, REFRESH PUBLICATION veya REFRESH SEQUENCES — alınan bir snapshot. Refresh'in açıkça çalıştırılması subscriber'daki değeri yaklaşık 118 milisaniyede 1.500'e taşıdı.
Özelliğin önlemek için var olduğu hatanın yeniden üretilmesi
Yazar daha sonra publisher'a 200 satır daha ekleyerek toplamı tamamen replike edilmiş 1.700 satıra çıkardı ve simüle edilmiş bir promote gerçekleştirdi: subscription'ı devre dışı bıraktı, sildi ve sequence'ları önce refresh etmeden yerel olarak insert yaptı; çünkü önceki refresh yeni grubun gelmesinden önce yapılmıştı. Insert, id 1501 üzerindeki yinelenen anahtar ihlaliyle başarısız oldu. Çıkarım şu: sequence'ları refresh etmek, operatörün promote öncesinde yaptığı son şey olmalı, subscription'ın yaşam döngüsündeki daha erken bir noktada yapılan bir işlem değil — bu adımı dokümantasyon anıyor ama, yazıya göre öne çıkarmıyor.
Yeni sequence'ların önceden oluşturulması gerekiyor
Yazar ayrıca bir subscription zaten varken sequence'ların sonradan ortaya çıkması yaygın senaryosunu test etti: publisher'da 300 ek sequence oluşturdu ve subscriber'dan publication'ı refresh etmesini istedi. Komut, eksik bir relation nedeniyle hata verdi ve 300 sequence'ın hiçbiri oluşturulmadı. Davranış ya hep ya hiç şeklinde ve yazarın testlerinde, subscription'ın sequence'ları hiç tanıması için bunların subscriber üzerinde nesne olarak zaten mevcut olması gerekiyordu. Dokümante edilen çözüm, subscriber üzerinde eşleşen sequence'ları elle oluşturmaktır; bu yapıldıktan sonra her iki refresh komutu da 200 milisaniyenin altında tamamlandı ve subscriber'daki sequence sayısı birden 301'e çıktı.
Maliyet ve gözlemlenebilirlik
Ölçülebilir anlamda bir maliyet yoktu: tek bir sequence'ı veya 301 tanesini refresh etmek de 200 milisaniyenin altında tamamlandı. pg_stat_subscription_stats üzerindeki yeni sync_seq_error_count sütunu, bu yolu üretim ortamında izlemek için tasarlanmış.
Neden önemli
Sequence durumu, uzun süredir ekipleri failover ve sürüm yükseltmeleri için fiziksel replikasyona iten sessiz engeldi; bunun bedeli de tablo düzeyinde filtreleme kaybıydı. PostgreSQL 19 bu boşluğun büyük kısmını kapatıyor ve ilk senkronizasyon davranışı, az önce promote edilmiş subscriber'larda ID çakışmalarını gerçekten önlüyor. Ancak sequence senkronizasyonu sürekli değil olay güdümlü olduğu için failover runbook'ları, promote hemen öncesinde zorunlu bir adım olarak son bir REFRESH SEQUENCES ele almalı ve şema sapması (schema drift) hâlâ yeni sequence'ların subscriber üzerinde elle oluşturulmasını gerektiriyor. Bir uyarı: bunların tamamı RC1 üzerinde test edildi ve genel kullanıma sunulma 19 Kasım 2026 olarak planlandı, bu yüzden ayrıntılar nihai sürümden önce hâlâ değişebilir.
- #postgresql
- #logical-replication
- #databases
- #failover
- #data-recovery