Postgres’te Değişiklikleri Yakalamanın Yolları
(blog.sequin.io)- Postgres değişikliklerini diğer sistemlere gerçek zamanlı aktarmak için CDC (Change Data Capture) gerekir; basit bildirimlerden WAL tabanlı replikasyona kadar seçeneklerin güvenilirliği ve operasyon yükü oldukça farklıdır
- Listen/Notify en hafif başlangıç yoludur; ancak at-most-once teslimat, geçici bildirimler ve 8000 bayt payload sınırı nedeniyle temel CDC’den çok yardımcı bir sinyale benzer
- Tablo polling’i ve denetim tablosu (outbox pattern) standart tablolar ve trigger’larla uygulanabilir; ancak silme algılama, diff, commit sırası, yazma çoğalması ve backpressure sorunlarını sizin çözmeniz gerekir
- Mantıksal replikasyon (logical replication) WAL’dan insert/update/delete işlemlerini stream eden güçlü bir yöntemdir; ancak replication slot, ack, yeniden başlatma ve throughput yönetimini uygulamanın üstlenmesi gerekir
- Sequin, Postgres mantıksal replikasyonunu temel alarak değişiklikleri SQS, Kafka, Elasticsearch, Redis, HTTP endpoint’leri gibi hedeflere iletir ve replication slot’ları doğrudan yönetme yükünü azaltır
Postgres CDC’ye Ne Zaman İhtiyaç Duyulur?
- Postgres, saklanan verileri yönetmede güçlüdür; ancak tablo değişiklikleriyle workflow tetiklemek veya verileri başka veri depolarına, sistemlere ya da servislere gerçek zamanlı stream etmek için veri hareketini ayrıca tasarlamak gerekir
- Change Data Capture (CDC), veritabanı değişikliklerini belirleyip yakaladıktan sonra downstream sistemlere gerçek zamanlı aktarma yöntemidir
- Postgres’te değişiklik yakalamanın birçok yolu vardır; uygulama zorluğu, güvenilirlik ve operasyon yükü birbirinden farklıdır
Listen/Notify: En Basit pub-sub
- Postgres’in Listen/Notify özelliği süreçler arası iletişim sağlar ve publish-subscribe paterniyle çalışır
- Bir session belirli bir kanalı
listeneder; veritabanı aktiviteleri veya başka session’lar bu kanalanotifygönderebilir - Değişiklik yakalamak için trigger eklenerek kullanılabilir
- Örnek bir trigger,
after insert or update or deleteanında değişen kaydıntable,id,actionbilgisini JSON’a çevirir vepg_notify('table_changes', payload::text)çağırır
- Örnek bir trigger,
- Sınırları belirgindir
- at-most-once teslimat semantiğine sahiptir; listener, bildirimin yayınlandığı anda bağlı olmalıdır
- listener yalnızca abone olduktan sonraki bildirimleri alır; bu nedenle kısa bir ağ kesintisinde bile bildirim kaçırabilir
- Payload boyutu sınırı 8000 bayttır; aşılırsa
notifykomutu başarısız olur - Payload boyutuna kanal adı da dahildir; Postgres identifier’ları gibi kanal adı en fazla 64 bayt olabilir
- Temel değişiklik algılama veya tablo polling optimizasyonu için kullanılabilir; ancak karmaşık CDC gereksinimlerine pek uygun olmayabilir
Tablo Polling’i: Basit, Ama Silme ve Diff Konusunda Zayıf
- En basit sağlam değişiklik yakalama yöntemi, tabloyu doğrudan polling ile taramaktır
- Her tabloda, satır her güncellendiğinde yenilenen
updated_atbenzeri bir kolon gerekir; gerekirse trigger ile oluşturulabilir updated_atveidkombinasyonu cursor olarak kullanılır; uygulama mantığı cursor’ı saklar ve yönetir- Notify aboneliği de birlikte kullanılırsa, kayıt ekleme veya güncelleme olduğunu uygulamaya bildirerek polling sıklığı azaltılabilir
- Postgres bildirimleri geçici olduğundan, bunları yalnızca polling üzerinde bir optimizasyon olarak kullanmak daha uygundur
- Başlıca üç dezavantajı vardır
- Silinen satırlar tabloda kalmadığı için silme algılama mümkün değildir
- Buna çözüm olarak bir delete trigger’ının
idve gerekli kolonlarıdeleted_contactsgibi ayrı bir tabloya yazması, uygulamanın da bu tabloyu polling ile okuması sağlanabilir - Bir kaydın güncellendiği anlaşılabilir, ancak neyin değiştiği bilinemez
- Postgres datetime ve sequence değerlerinde commit sırası sapabildiğinden,
updated_attemelinde bir bloğu okurken hâlâ commit sürecindeki satırlar kaçırılabilir
- Silme, diff ve ara sıra yaşanan kaçırmalar büyük sorun değilse, basit değişiklik takibi için makul bir seçenektir
Denetim Tablosu: outbox pattern ile Değişiklik Günlüğü Saklama
- Denetim tablosu (audit table) yöntemi, değişiklikleri ayrı bir
changelogtablosuna kaydeder; outbox pattern olarak da bilinir changelogiçinde değişiklikle ilgili kolonlar bulunabiliraction:insert,update,deleteolup olmadığıold: değişiklik öncesi kaydınjsonbdeğeri; insert için boşturvalues: değişen alanlarınjsonbdeğeri; delete için boşturinserted_at: değişikliğin gerçekleştiği zaman
- Uygulamak için her değişiklikte
changelogtablosuna insert yapan bir trigger fonksiyonu ve izlenecek her tablo için trigger gerekir changelog’u kuyruk gibi tüketmek de mümkündür- Uygulama worker’ı tablodan değişiklikleri alır
- Yaklaşık exactly-once işleme için Postgres’in
for update skip lockedözelliği kullanılabilir - Worker bir transaction açıp
order by timestamp limit 100 for update skip lockedile bir batch’i kilitleyebilir, işleyebilir, işlenen kayıtları silebilir ve ardından commit edebilir
- Operasyonel dezavantajları vardır
- Tek bir tablo yazımı, denetim tablosunda birden fazla yazım üreten yazma çoğalması (write amplification) yaratır
- Genellikle denetim tablosuna ilk insert, işleme sırasında update ve işlemden sonra delete olmak üzere en az üç yazma oluşur
- Worker’lara fan-out etme biçimi, uygulamaya göre ayrıca tasarlanmalıdır
- Prodüksiyon ölçeğinde dağıtımdan önce trigger fonksiyonunu ve tablo tasarımını ayarlamak gerekebilir
- Bir worker’ın değişikliği checkout edilmiş halde ne kadar tutabileceğine ilişkin zaman sınırı gibi ayrıntılı politikalar da düşünülebilir
- Worker başarılı şekilde işleyemese bile denetim tablosu dolmaya devam eder; bu nedenle backpressure yönetimi yetersizdir
Foreign Data Wrapper: Belirli Postgres’ler Arası Senkronizasyona Daha Yakın Bir Seçenek
- Foreign Data Wrapper (FDW), Postgres veritabanının harici veri kaynaklarını okuyup yazmasını sağlayan bir özelliktir
- En yaygın desteklenen FDW tabanlı eklenti
postgres_fdw’dir- İki Postgres veritabanını bağlayabilir ve bir veritabanında diğer veritabanının tablolarına referans veren view benzeri bir yapı oluşturabilirsiniz
- İçeride bir Postgres veritabanı client, diğeri server olur
- Foreign table’a sorgu atıldığında client veritabanı, server veritabanına Postgres wire protocol üzerinden sorgu gönderir
- FDW, değişiklik yakalama yöntemi olarak yaygın değildir ve çok spesifik durumlar dışında önerilmesi zordur
- Bir Postgres veritabanındaki değişiklikleri başka bir Postgres veritabanına yazmak istiyorsanız FDW uygun olabilir
- Örnek olarak muhasebe veritabanı ile uygulama veritabanının ayrı kullanıldığı bir durum verilebilir
- Ara değişiklik yakalama adımını atlayıp
postgres_fdwile veritabanları arasında doğrudan yansıtma yapılabilir
- Dahili API’ye değişiklikleri POST eden özel bir FDW yazmak da mümkündür
- API’ye commit içinde yazdığı için API değişikliği reddedebilir ve commit’i rollback edebilir
- FDW güçlüdür; ancak CDC amacıyla en iyi seçenek olduğu durumlar nadirdir ve özel FDW yazmak değişiklik yakalama yöntemleri arasındaki en büyük işlerden birine yakındır
- Özel FDW yazmak Supabase wrappers gibi araçlarla kolaylaşmıştır; yine de büyük bir iştir
Doğrudan Mantıksal Replikasyon: WAL Tabanlı Güçlü CDC
- Postgres’in veritabanı replikasyonu için bir protokolü vardır; bunlardan biri mantıksal replikasyon (logical replication)’dır
- Mantıksal replikasyon, Postgres’in WAL (write-ahead log) altyapısı üzerine kuruludur
- Veritabanındaki tüm insert, update ve delete işlemleri izlenir
- Değişiklikler subscriber’a stream edilir
- Kullanıcı önce primary üzerinde bir replication slot oluşturur
pg_create_logical_replication_slot('<your_slot_name>', '<output_plugin>')biçimi kullanılır
output_plugin, WAL değişikliklerini decode edecek eklentiyi belirtirpgoutputvarsayılan eklentidir ve client server’ın beklediği binary formatta çıktı üretirtest_decoding, WAL değişikliklerini insan tarafından okunabilir biçimde sunan basit bir output plugin’idir- Postgres’in yerleşik eklentisi olmasa da popüler bir eklenti olan
wal2jsonvardır; JSON, uygulamaya başlamak için Postgres binary formatına göre daha kolay işlenir
- Replication slot oluşturulduktan sonra başlatılabilir ve tüketilebilir
- Replication slot, standart sorgulardan farklı bir Postgres protokol alanını kullanır
- Birçok client kütüphanesi replication slot işlemlerine yardımcı fonksiyonlar sunar
psycopg2örneği, WAL mesajlarını tüketmek içincursor.start_replication(...)vecursor.consume_stream(...), ack göndermek içincursor.send_feedback(flush_lsn=msg.wal_end)kullanır
- Client, aldığı WAL mesajlarına ack göndermelidir; replication slot, offset’i olan Kafka’ya benzer şekilde çalışır
- Mantıksal replikasyon CDC için tasarlanmış sağlam bir yöntemdir, ancak karmaşıktır
- Replication slot ve replication protocol, geliştiricilere sıradan tablolar ve sorgular kadar tanıdık değildir
- Yeniden başlatma sırasında mesaj kaçırmamak için bir strateji gerekir
- Postgres’ten gelen yüksek hacimli mesajları işleyebilecek şekilde tasarlanmalıdır
Sequin: Mantıksal Replikasyonu Saran Bir CDC Aracı
- Sequin, Postgres değişikliklerini ve satırlarını kuyruklara, stream’lere, arama indekslerine, cache’lere, HTTP endpoint’lerine vb. ileten bir CDC aracıdır
- Hedefler arasında SQS, Kafka, Elasticsearch, Redis, HTTP endpoint’leri gibi seçenekler bulunur
- Sequin içeride Postgres mantıksal replikasyonunu kullanır, ancak low-level protokol karmaşıklığını soyutlar
- insert, update ve delete işlemlerinin tamamını yakalayabilir; update ve delete sırasında satırın hem
newhem deolddeğerlerini yakalar - Sequin’i düşünmek için koşullar şunlardır
- Gerçek zamanlı CDC’ye ihtiyacınız vardır
- SQS veya webhook gibi hedeflere aracı sistem olmadan doğrudan stream etmek istersiniz
- Geçmiş veri backfill’i ve SQL
wherekoşuluna dayalı değişiklik filtreleme gibi özelliklere ihtiyacınız vardır - Replication slot’ları doğrudan yönetmekten daha basit bir alternatif gerekir
- exactly-once işleme garantisine ihtiyacınız vardır
- Dezavantajları da vardır
- Sequin, Postgres içinde çalışan bir eklenti değil, veritabanının yanında çalışan üçüncü taraf bir araçtır
- Eklenti olmadığı için herhangi bir Postgres veritabanıyla geniş uyumluluk sunar; ancak Sequin Cloud kullanmıyorsanız ek altyapıyı kendiniz kurmanız gerekir
Seçim Kriterleri
- Başlangıç aşamasında Listen/Notify ve tablo polling’i uygundur
- Listen/Notify, kritik olmayan event yakalama, prototipleme ve polling optimizasyonu için iyidir
- Polling, basit kullanım senaryoları için makul ve doğrudan bir çözümdür
- Biraz daha ciddi aşamada denetim tablosu ara seçenek olabilir
- Satırın
newveoldpayload’larını yakalayabilir - Doğru kurulursa exactly-once işleme sistemi elde edilebilir
- Ölçeklenirken yazma çoğalması ve backpressure eksikliği sorun olur; manuel yapılandırmada hata yapılırsa mesaj kaybedilebilir
- Satırın
- Ölçeklenme aşamasında mantıksal replikasyon sağlam çözüme en yakın yoldur
- Ancak slot’tan doğrudan okumak yerine Sequin gibi bir araç kullanmak önerilir
- FDW ilginç bir özelliktir; ancak genel CDC gereksinimlerini çözme olasılığı düşüktür
1 yorum
Hacker News yorumları
Trigger + geçmiş tablosu (denetim tablosu) vakaların %98’inde doğru çözümdür. Zaten kullanmıyorsanız bugünden itibaren kullanabilirsiniz. 30 yıldan uzun süredir kendini kanıtlamış bir tekniktir.
Genel biçimde uygulamanın basit bir örneği https://gist.github.com/slotrans/353952c4f383596e6fe8777db5d... adresinde var. Alan verimliliğinden vazgeçip “kolay uygulamayı” seçen bir yaklaşım.
Değişmez verileri saklayabiliyorsanız gerçekten harika; ancak veritabanınızda muhtemelen çok fazla değişebilir veri vardır ve her gün pek çok şeyi unutuyor olabilirsiniz. Unutmayın, geçmiş tablosu kullanın.
Referans: https://github.com/matthiasn/talk-transcripts/blob/master/Hi...
Papertrail gibi uygulama katmanındaki geçmiş izleme kütüphanelerini veya tekniklerini kullanmamak daha iyi. Yavaştırlar, hataya açıktırlar ve uygulama stack’ini baypas eden DB değişikliklerini yakalayamazlar.
updatedzaman damgasını uygulamadan basmaya çalışmak da temelde yanlıştır; çünkü her web sunucusunun saati farklıdır. DB saatini kullanmalısınız; doğru olan tek saat odur.now()gibi bir çağrı koyup DB saatini kullanmak doğru yaklaşımdır.Ancak yalnızca bu zaman damgasıyla senkronizasyon yapmak yeterli değildir. Çünkü zaman damgası, transaction commit anında değil transaction başlangıç anında oluşturulur.
Tabloyu poll ederek son zaman damgasına göre filtrelerseniz, commit sırası karışmış transaction’ların bir kısmını kaçırabilirsiniz. Birkaç dakika daha geriye bakan ve tekrarları eleyen bir tampon aralık koyabilirsiniz; ancak PostgreSQL’de transaction süresi sınırsızdır ve çok geriye bakmak ciddi israf yaratır. Doğruluk ve verimlilik önemliyse bu yöntem uygun değildir.
Log sıra numarası, DB zamanı ve
REPLICA IDENTITY FULLkullanıldığında değişiklik öncesi/sonrası durumlar da dahil edilir. Sonrasında koleksiyonu Snowflake gibi bir yerde materialize ederseniz, kaynak DB güncellemelerini takip eden senkronize bir tabloyu varsayılan olarak elde edebilirsiniz.Aynı temel data lake üzerinden denetim amaçlı tam tablo geçmişini dönüştürmek veya materialize etmek de mümkündür; böylece kaynak DB’ye tekrar capture ya da WAL reader bağlamaya gerek kalmaz.
Benzer deseni JSON yerine sütun tabanlı olarak uygulayan SQLite yöntemini de ayrıca anlattım: https://simonwillison.net/2023/Apr/15/sqlite-history/
Bu yazı, Postgres’in yerleşik özellikleriyle mümkün olan çeşitli yaklaşımları kısa ve iyi bir şekilde özetliyor.
“Değişiklikleri denetim tablosunda yakalama” bölümünde, önceki şirketimde Temporal Tables desenini faydalı şekilde kullanmıştık. Diğer başlıca ilişkisel DBMS’lerden farklı olarak Postgres’in kendisinde yerleşik değil; ancak SQL fonksiyonuyla kullanılabilen basit bir desen var: https://github.com/nearform/temporal_tables
Belirli bir andaki tablo durumunu görebildiğiniz için “12 Ağustos’ta bu kullanıcının ayarları neydi?”, “Dün gece 23:55’te kaç bekleyen kayıt vardı?”, “Şu an ile bir hafta önceki feature flag farklarını göster” gibi sorulara yanıt verebilirsiniz.
Daha önce çok büyük bir monolitik SQL Server’ı olan bir şirkete danışmanlık yapmıştım. Postgres değildi ama Postgres olduğunu varsaysak da durum benzer olurdu.
Onlarca yıl boyunca işletimde kalmış, şirket içindeki türlü türlü amaçlar için kullanılmıştı; fiilen şirket genelindeki tüm uygulamalar ve iş süreçleri verilerini bu veritabanına kaydediyordu.
Sorun şuydu: Bu DB’yi sorgulayan çok sayıda uygulama vardı; veri ekleyen ve değiştiren süreçler ile prosedürler de inanılmaz fazlaydı. Üst taraftaki ekleme/değiştirme süreçleri değiştikçe veya yenileri eklendikçe uygulama düzeyindeki değişmez koşulların bozulduğu durumlar ortaya çıkıyordu. Normal süreçler bile kötü veri olduğunda farklı davranıyordu.
Kök nedeni izlemek çok zordu; çünkü incelenen şeyler çoğunlukla 10 yıl önce yazılmıştı ve o çalışanlar çoktan şirketten ayrılmıştı.
Postgres veritabanındaki değişiklikleri bir tür DAG biçiminde yakalayıp hangi sürecin veriyi eklediğini, değiştirdiğini, sildiğini ve tarihsel olarak nasıl davrandığını; farklı uygulamaların bu veriyi nasıl sorguladığını ve sorgu istatistiklerinin zaman içinde nasıl değiştiğini görebilir miyiz diye merak ediyorum.
Böyle bir öncül örnek var mı, böyle bir aracı hangi yaklaşımla geliştirmek mümkün olur, pek emin değilim. Geçmişte benzer bir şey yapmayı düşünmüştüm ama doğru tercihler yapabilmek için Postgres çekirdek mühendisi düzeyinde anlayış gerektiren bir alan gibi geliyor.
Her değişiklik için istemci düzeyinde kaynak verisini alamazsınız.
Yine de etrafından dolaşmak mümkün. Mantıksal replikasyon akışı
pg_logical_emit_messagefonksiyonunun bilgi mesajlarını da içerebildiğinden, istemci doğrudan metadata ekleyebilir. Her transaction başlangıcında istemci tanımlayıcısını yayacak şekilde ayarlamak da mümkün olabilir.last updated by) izleyen bir kolon koyarım. Bir anti-pattern olabilir; daha sağlam bir çözüm varsa iyi olurdu.Bu yaklaşım WAL veya trigger kullanan neredeyse tüm SQL ailesi çözümlerinde çalışır.
SQL Server’da trigger yaklaşımını birkaç kez kullandım ama tüm sorguları loglayınca yavaşlama eğilimi oluyor. İşletimi engellemeyen bir insert mekanizması tasarlamak kusursuz değil; sampling gerekebilir.
“Audit table” yoluna gidecekseniz doğrudan pgaudit kullanın. Sahada kendini kanıtlamış bir extension ve AWS kullanıyorsanız RDS’de de mevcut.
https://github.com/pgaudit/pgaudit/blob/master/README.md
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appen...
https://github.com/arkhipov/temporal_tables
https://news.ycombinator.com/item?id=26748096
Bunu illa yapmanız gerekmiyor. Bunu istemek, Postgres’teki ilişkileri sözleşmeye dönüştürmek demek. Hiçbir servis iç durumunu kalıcı hale getiremez olur.
Domain-driven design’a gerçekten kendinizi adarsanız mümkün olabilir; ama hafif ve pratik bir event-driven system kullanmak daha iyi.
Event-driven herhangi bir şey 1000 kat daha karmaşık.
updated_atkolonunu polling ile kontrol etme yöntemi, en basit biçimiyle sağlam değildir. Çünkü transaction’ların o sırayla commit edileceğinin garantisi yoktur.updated_atdeğeri2023-09-22 12:00:01olarak ayarlanır.Kısa süre sonra transaction B başlar, Row 2’nin
updated_atdeğeri2023-09-22 12:00:02olarak ayarlanır ve B önce commit eder.Polling sorgusu çalışır, Row 2’yi en son değişiklik olarak görüp cursor’ı
2023-09-22 12:00:02olarak günceller; ardından A daha sonra commit ederse Row 1 kaçırılır.Bu sorundan kaçınmanın basit yolu neredeyse gerçek zamanlı polling yapmamaktır. Sıra eninde sonunda tutarlı hale gelir.
Daha sağlam öneri sequence kullanmak olabilir. Örneğin satır her değiştiğinde artan bir
updated_at_idxkolonu tutmak gibi.now()koyan bir before trigger kullanıldığında da iki satırınupdated_attimestamp’leri transaction commit sırasından farklı olabilir mi merak ediyorum.updated_atile commit timestamp’inin aynı olması gerekmez amaupdated_at, milisaniye/mikrosaniye düzeyinde commit sırasını doğru göstermeli.updated_atyerine, trigger’ın mevcut transaction ID ile ayarladığı_txidkolonunu kullanıyoruz. Sonraki polling’detxid_current()ile hangi transaction’ların commit edildiğini, hangilerinin henüz edilmediğini kontrol ediyoruz.Biraz riskli ve sınır değeri hatası üretmeye çok açık ama yıllardır production’da sorunsuz çalışıyor.
Yazı harika.
Elixir ve Postgres kullanıyorsanız, benzer bir yaklaşımla WAL değişikliklerini dinleyen küçük bir kütüphane hazırlamıştım: https://github.com/cpursley/walex
Bu yöntemlerin hepsi biraz kötü; kişisel olarak polling’in en pratik seçenek olduğunu düşünüyorum
Postgres’in bu alanda yenilik yapması iyi olurdu
SQL standardına girmeden, ilişkisel DBMS’lerin çekirdek alanında ivme kazanmasının zor olduğunu düşünüyorum. Seçenekler çok ve karmaşık; kullanıcı alanındaki başarılı çözümler de performans açısından aşırı yük getiren türden değil
Bu arada, bu alanı araştıranlar genelde denetim tabloları yaklaşımına meylediyor. Çünkü veritabanı içinde tutarlı ACID özellikleri korunuyor ve proxy ya da polling işi eklemek yerine Postgres tek hata noktası olarak kalıyor
Veri dünyasında büyük bir boşluk var. Veri deposuna sonuçları sormak yerine, sorgu sonuçlarının artımlı olarak push edilmesi iyi olurdu
Gerçek zamanlı/streaming analizleri çok yapıyoruz; stream processing yapılabiliyor ve veri deposunun içinde materialized view’larla bunun bir kısmı ele alınabiliyor. Ama veri DB’ye ya da data lake’e girdikten sonra, aşağı akışta değişiklikleri görmek için pratikte yine polling’e dönülüyor
Veride belirli bir durum oluştuğunda tepki vermek ya da sayfayı yenilemeden ekranı güncellemek için pek temiz çözüm yok. Bu yazıdaki çözümler de birinci sınıf özellik olmaktan çok geçici çözüm gibi görünüyor
Sayfa yenilemeden gerçek zamanlı güncellenen bir rapor yapmak istiyorsanız, genelde veriyi DB’den yükleyip değişiklikleri Kafka ve WebSocket ile GUI’ye akıtma yoluna gidiliyor. Böylece bazı analizlerin kodda, bazılarının DB’de yapıldığı tuhaf bir lambda mimarisi işletmiş oluyorsunuz
Bu alanda yenilikler var. KSQL ve Kafka Streams değişiklikleri dışarı verebiliyor, Materialize’da abonelikler var, ClickHouse’ta live view’lar var. Ama birçok özellik yeni ya da preview aşamasında ve tam oturmuyor. Hepsini denedim; geliştiriciye fazla iş yıktığını hissettim
[select * from orders with suscribe]gibi bir seçenekle doğrudan değişiklik feed’i alabileceğiniz bir kütüphane olsa güzel olurdu. Yeterince önemli bir alan ama hak ettiği ilgiyi daha az gördüYazıda ele alınmayan büyük bir replikasyon tuzağı var; bu yüzden ben replikasyon kullanmıyorum
Postgres, replikasyon slotu tüketicisinin veriyi kaçırmamasını çok güçlü biçimde garanti etmeye çalışıyor. Bu yüzden tüketici slottan veri tüketmezse Postgres kaçırılan veriyi nazikçe saklamaya devam ediyor ve sonunda disk dolup DB çökene kadar gidiyor. Prototipleme sırasında iki farklı SaaS DB’de bunu yaşadım; kurtarmak için destek bileti açmaktan başka çare yoktu
Replikasyon slotu tüketicisi okumayı bırakırsa mutlaka alarm çalmalı
Bir diğer neden de tablonun ilk snapshot’ını alan kod yolu ile değişiklikleri okuyan kod yolunun tamamen farklı olması. Hiçbir değişikliği kaçırmayacak şekilde replikasyon slotu okumasını başlatmak önemsiz bir iş değil
Ne yazık ki değişiklik yakalama açısından replikasyon en az hacky çözüm
Ben polling kullanıyorum ama
updated_atyerine txid saklıyorumHangi davranışı daha çok istediğinizi merak ediyorum
Büyük veri hacimleriyle çalışıyorsanız ilk snapshot ile değişiklik okumayı farklı ele almak istersiniz. Çünkü paralel başlatma ya da fiziksel yedek tabanlı başlatma gibi işlemlerin mümkün olması gerekir. Yine de slot oluşturulduktan sonra mevcut verileri seçici olarak stream eden bir özelliğin faydalı olabileceğini anlıyorum
Değişiklikleri kaçırmamak için replikasyon slotu okumasını başlatma kısmının zor olmaması gerekir gibi geliyor; nerede takıldığınızı merak ediyorum
Tüm değişikliklere ihtiyaç olmadığında, bağlantı kesildiğinde kendini temizleyen geçici replikasyon slotları da kullanışlıdır. Sunucuyu öldürmemek için tutulan WAL’a maksimum sınır koyan bir yapılandırma da var
updated_atyerine txid’yi nasıl kullandığını biraz daha açıklarsan iyi olurdu