- Untuk meneruskan perubahan Postgres ke sistem lain secara real-time, diperlukan CDC (Change Data Capture), dan tiap opsi—mulai dari notifikasi sederhana hingga replikasi berbasis WAL—memiliki perbedaan besar dalam keandalan dan beban operasional
- Listen/Notify adalah cara paling ringan untuk memulai, tetapi karena semantik pengiriman at-most-once, notifikasi yang bersifat sementara, dan batas payload 8000 byte, pendekatan ini lebih cocok sebagai sinyal pendukung daripada CDC inti
- Polling tabel dan tabel audit (outbox pattern) bisa diimplementasikan hanya dengan tabel dan trigger standar, tetapi deteksi penghapusan, diff, urutan commit, write amplification, dan backpressure harus ditangani sendiri
- Replikasi logis (logical replication) adalah cara yang kuat untuk melakukan streaming insert/update/delete dari WAL, tetapi aplikasi harus mengelola replication slot, ack, restart, hingga penanganan throughput
- Sequin, yang dibangun di atas replikasi logis Postgres, meneruskan perubahan ke SQS, Kafka, Elasticsearch, Redis, HTTP endpoint, dan lainnya sehingga mengurangi beban mengelola replication slot secara langsung
Kapan Postgres CDC dibutuhkan
- Postgres kuat untuk mengelola data yang tersimpan, tetapi jika Anda ingin memicu workflow dari perubahan tabel atau melakukan streaming secara real-time ke penyimpanan data, sistem, atau layanan lain, maka perpindahan data harus dirancang secara terpisah
- Change Data Capture (CDC) adalah pendekatan untuk mengidentifikasi dan menangkap perubahan database, lalu meneruskannya secara real-time ke sistem downstream
- Ada beberapa cara untuk menangkap perubahan di Postgres, dan masing-masing berbeda dalam tingkat kesulitan implementasi, keandalan, dan beban operasional
Listen/Notify: pub-sub paling sederhana
- Listen/Notify di Postgres adalah fitur komunikasi antarproses yang bekerja dengan pola publish-subscribe
- Sebuah sesi dapat
listenpada channel tertentu, dan aktivitas database atau sesi lain dapat mengirimnotifyke channel tersebut - Untuk change capture, fitur ini bisa digunakan dengan menambahkan trigger
- Contoh trigger membuat JSON berisi
table,id, danactiondari record yang berubah pada saatafter insert or update or delete, lalu memanggilpg_notify('table_changes', payload::text)
- Contoh trigger membuat JSON berisi
- Keterbatasannya cukup jelas
- Memiliki semantik pengiriman at-most-once, dan listener harus terhubung saat notifikasi diterbitkan
- Listener hanya menerima notifikasi sejak mulai berlangganan, jadi jika koneksi sempat terputus karena masalah jaringan, notifikasi bisa terlewat
- Batas ukuran payload adalah 8000 byte, dan jika melebihi batas ini, perintah
notifyakan gagal - Ukuran payload juga mencakup nama channel, dan seperti identifier Postgres, nama channel dapat memiliki panjang maksimum 64 byte
- Cocok untuk deteksi perubahan dasar atau optimasi polling tabel, tetapi mungkin kurang sesuai untuk kebutuhan CDC yang lebih kompleks
Polling tabel: sederhana tetapi lemah untuk penghapusan dan diff
- Cara change capture yang paling sederhana namun andal adalah dengan melakukan polling langsung pada tabel
- Tiap tabel memerlukan kolom seperti
updated_atyang diperbarui setiap kali baris diubah, dan bila perlu bisa dibuat dengan trigger - Kombinasi
updated_atdaniddigunakan sebagai cursor, lalu logika aplikasi menyimpan dan mengelola cursor tersebut - Jika digabungkan dengan langganan Notify, aplikasi dapat diberi tahu bahwa ada insert atau update record sehingga frekuensi polling bisa dikurangi
- Karena notifikasi Postgres bersifat sementara, pendekatan ini lebih tepat dipakai hanya sebagai optimasi di atas polling
- Ada tiga kelemahan utama
- Baris yang dihapus tidak lagi ada di tabel, sehingga deteksi penghapusan tidak dimungkinkan
- Sebagai solusi, trigger delete bisa menyimpan
iddan kolom yang diperlukan ke tabel terpisah sepertideleted_contacts, lalu aplikasi melakukan polling ke tabel itu - Anda bisa tahu bahwa sebuah record telah di-update, tetapi tidak bisa tahu apa yang berubah
- Karena datetime dan sequence di Postgres bisa tidak selaras dengan urutan commit, saat membaca blok berdasarkan
updated_at, Anda bisa melewatkan baris yang masih dalam proses commit
- Ini adalah pilihan yang masuk akal untuk pelacakan perubahan sederhana ketika penghapusan, diff, dan kehilangan sesekali bukan masalah besar
Tabel audit: menyimpan log perubahan dengan outbox pattern
- Pendekatan tabel audit (audit table) mencatat perubahan ke tabel
changelogterpisah, dan juga dikenal sebagai outbox pattern changelogdapat memiliki kolom-kolom terkait perubahanaction: apakahinsert,update, ataudeleteold:jsonbdari record sebelum perubahan, kosong untuk insertvalues:jsonbdari field yang berubah, kosong untuk deleteinserted_at: waktu terjadinya perubahan
- Untuk mengimplementasikannya, Anda memerlukan fungsi trigger yang melakukan insert ke
changelogsetiap kali ada perubahan, serta trigger untuk setiap tabel yang ingin dipantau changelogjuga bisa dikonsumsi seperti antrean- Worker aplikasi mengambil perubahan dari tabel
- Untuk pemrosesan yang mendekati exactly-once, Anda bisa menggunakan
for update skip lockeddari Postgres - Worker dapat membuka transaksi, mengunci satu batch dengan
order by timestamp limit 100 for update skip locked, memprosesnya, menghapus record yang sudah selesai diproses, lalu commit
- Ada kelemahan dari sisi operasional
- Satu penulisan ke tabel utama dapat menghasilkan beberapa penulisan ke tabel audit, yaitu write amplification
- Umumnya akan ada setidaknya tiga kali penulisan: insert awal ke tabel audit, update saat diproses, dan delete setelah selesai diproses
- Pendekatan fan-out lewat worker harus dirancang sendiri sesuai kebutuhan aplikasi
- Sebelum deployment skala produksi, kemungkinan Anda perlu menyesuaikan fungsi trigger dan desain tabel
- Anda juga mungkin perlu mempertimbangkan kebijakan detail seperti batas waktu berapa lama worker boleh mempertahankan perubahan yang sudah di-checkout
- Jika worker gagal memproses dengan sukses, tabel audit akan terus menumpuk sehingga penanganan backpressure kurang memadai
Foreign Data Wrapper: opsi yang lebih dekat ke sinkronisasi antar-Postgres tertentu
- Foreign Data Wrapper (FDW) adalah fitur yang memungkinkan database Postgres membaca dan menulis ke sumber data eksternal
- Ekstensi berbasis FDW yang paling luas didukung adalah
postgres_fdw- Anda dapat menghubungkan dua database Postgres dan membuat struktur mirip view di satu database yang merujuk ke tabel di database lain
- Secara internal, satu database Postgres bertindak sebagai klien dan database lainnya sebagai server
- Saat foreign table di-query, database klien mengirim query ke database server melalui wire protocol Postgres
- FDW bukan pendekatan yang umum untuk change capture dan sulit direkomendasikan di luar situasi yang sangat spesifik
- Jika Anda ingin menulis perubahan dari satu database Postgres ke database Postgres lain, FDW bisa cocok
- Contohnya adalah ketika database akuntansi dan database aplikasi dipisahkan
- Anda bisa melewati tahap change capture perantara dan langsung merefleksikan perubahan antar-database dengan
postgres_fdw
- Anda juga bisa membuat FDW sendiri untuk melakukan POST perubahan ke API internal
- Karena penulisan ke API terjadi di dalam commit, API bisa menolak perubahan dan menyebabkan commit di-rollback
- FDW memang kuat, tetapi jarang menjadi pilihan terbaik untuk CDC, dan menulis FDW sendiri termasuk pekerjaan paling besar di antara pendekatan change capture
- Menulis FDW sendiri menjadi lebih mudah dengan alat seperti Supabase wrappers, tetapi tetap merupakan pekerjaan besar
Replikasi logis langsung: CDC kuat berbasis WAL
- Postgres memiliki protokol untuk replikasi database, dan salah satunya adalah replikasi logis (logical replication)
- Replikasi logis dibangun di atas WAL (write-ahead log) Postgres
- Semua insert, update, dan delete di database dilacak
- Perubahan di-streaming ke subscriber
- Pengguna terlebih dahulu membuat replication slot di primary
- Bentuknya menggunakan
pg_create_logical_replication_slot('<your_slot_name>', '<output_plugin>')
- Bentuknya menggunakan
output_pluginmenentukan plugin untuk mendekode perubahan WALpgoutputadalah plugin bawaan, dan mengeluarkan format biner yang diharapkan oleh server klientest_decodingadalah plugin output sederhana yang menyediakan perubahan WAL dalam bentuk yang dapat dibaca manusia- Meski bukan plugin bawaan Postgres,
wal2jsonadalah plugin populer, dan JSON lebih mudah ditangani sebagai titik awal aplikasi dibanding format biner Postgres
- Setelah replication slot dibuat, proses dapat dimulai dan dikonsumsi
- Replication slot menggunakan area protokol Postgres yang berbeda dari query standar
- Banyak library klien menyediakan fungsi untuk membantu pekerjaan dengan replication slot
- Contoh
psycopg2menggunakancursor.start_replication(...)dancursor.consume_stream(...)untuk mengonsumsi pesan WAL, lalu mengirim ack dengancursor.send_feedback(flush_lsn=msg.wal_end)
- Klien harus melakukan ack terhadap pesan WAL yang diterima, dan replication slot bekerja mirip Kafka dengan offset
- Replikasi logis adalah pendekatan andal yang memang dibuat untuk CDC, tetapi kompleks
- Replication slot dan replication protocol lebih tidak familier bagi developer dibanding tabel dan query biasa
- Anda memerlukan strategi agar tidak kehilangan pesan saat restart
- Sistem juga harus dirancang agar mampu menangani volume besar pesan yang keluar dari Postgres
Sequin: alat CDC yang membungkus replikasi logis
- Sequin adalah alat CDC yang meneruskan perubahan dan baris dari Postgres ke antrean, stream, indeks pencarian, cache, HTTP endpoint, dan lain-lain
- Targetnya mencakup SQS, Kafka, Elasticsearch, Redis, HTTP endpoints, dan lainnya
- Sequin secara internal menggunakan replikasi logis Postgres, tetapi mengabstraksikan kompleksitas protokol level rendah
- Semua insert, update, dan delete bisa ditangkap, dan untuk update serta delete, Sequin menangkap nilai
newdanolddari baris - Kondisi yang cocok untuk mempertimbangkan Sequin adalah sebagai berikut
- Anda membutuhkan CDC real-time
- Anda ingin melakukan streaming langsung ke tujuan seperti SQS atau webhook tanpa sistem perantara
- Anda membutuhkan fitur seperti backfill data historis dan pemfilteran perubahan berbasis klausa SQL
where - Anda membutuhkan alternatif yang lebih sederhana daripada mengelola replication slot secara langsung
- Anda membutuhkan jaminan pemrosesan exactly-once
- Ada juga kekurangannya
- Sequin bukan ekstensi internal Postgres, melainkan alat pihak ketiga yang berjalan di samping database
- Karena bukan ekstensi, alat ini memiliki kompatibilitas luas dengan berbagai database Postgres, tetapi jika tidak menggunakan Sequin Cloud, Anda harus menyiapkan infrastruktur tambahan sendiri
Kriteria pemilihan
- Pada tahap awal, Listen/Notify dan polling tabel cocok digunakan
- Listen/Notify bagus untuk menangkap event yang tidak kritis, prototyping, dan optimasi polling
- Polling adalah solusi yang wajar dan lurus untuk use case sederhana
- Pada tahap yang sedikit lebih serius, tabel audit bisa menjadi pilihan menengah
- Bisa menangkap payload
newdanolddari baris - Jika dibuat dengan benar, Anda bisa mendapatkan sistem pemrosesan exactly-once
- Saat skala membesar, write amplification dan tidak adanya backpressure menjadi masalah, dan kesalahan dalam konfigurasi manual bisa membuat pesan terlewat
- Bisa menangkap payload
- Pada tahap skala, replikasi logis adalah solusi yang paling mendekati pendekatan andal
- Namun, lebih disarankan memakai alat seperti Sequin daripada membaca langsung dari slot
- FDW adalah fitur yang menarik, tetapi kecil kemungkinannya menyelesaikan kebutuhan CDC yang umum
1 komentar
Komentar Hacker News
Trigger + tabel histori (tabel audit) adalah jawaban yang tepat untuk 98% kasus. Kalau belum memakainya, mulai saja hari ini. Ini teknik yang sudah teruji selama lebih dari 30 tahun
Contoh sederhana untuk mengimplementasikannya secara generik ada di https://gist.github.com/slotrans/353952c4f383596e6fe8777db5d.... Pendekatan ini mengorbankan efisiensi ruang demi “implementasi yang mudah”
Kalau bisa menyimpan data immutable, itu sangat bagus, tetapi di database kemungkinan ada sangat banyak data mutable, dan setiap hari besar kemungkinan banyak hal terlupakan. Jangan lupa, pakai tabel histori saja
Referensi: https://github.com/matthiasn/talk-transcripts/blob/master/Hi...
Sebaiknya jangan memakai library atau teknik pelacakan histori di lapisan aplikasi seperti Papertrail. Itu lambat, rentan error, dan tidak bisa menangkap perubahan DB yang melewati stack aplikasi. Upaya memberi timestamp
updateddari aplikasi juga pada dasarnya keliru, karena setiap web server punya jam yang berbeda. Harus memakai jam DB, dan itulah satu-satunya jam yang benarnow()di dalam query untuk memakai jam DBNamun melakukan sinkronisasi hanya dengan timestamp ini tidak cukup. Sebab timestamp dibuat pada saat transaksi dimulai, bukan saat transaksi di-commit
Jika mem-poll tabel dan memfilter berdasarkan timestamp terbaru, sebagian transaksi dengan urutan commit yang saling terselip bisa terlewat. Bisa saja dibuat zona penyangga dengan mengambil data beberapa menit lebih jauh ke masa lalu lalu menghapus duplikat, tetapi di PostgreSQL durasi transaksi tidak dibatasi, dan mengambil terlalu jauh ke masa lalu sangat boros. Jika akurasi dan efisiensi penting, cara ini tidak tepat
Dengan log sequence number, waktu DB, dan
REPLICA IDENTITY FULL, status sebelum/sesudah perubahan juga ikut tercakup. Setelah itu, jika collection dimaterialisasi ke tempat seperti Snowflake, secara default Anda mendapatkan tabel sinkronisasi yang mengikuti update dari DB sumberDari data lake dasar yang sama, histori tabel lengkap untuk tujuan audit juga bisa ditransformasi atau dimaterialisasi, sehingga tidak perlu lagi memasang capture atau WAL reader pada DB sumber
Saya juga menjelaskan pendekatan SQLite yang mengimplementasikan pola serupa berbasis kolom, bukan JSON: https://simonwillison.net/2023/Apr/15/sqlite-history/
Artikel ini merangkum dengan ringkas berbagai pendekatan yang bisa dilakukan dengan fitur bawaan Postgres
Pada bagian “menangkap perubahan ke tabel audit”, di perusahaan sebelumnya kami memakai pola Temporal Tables dengan baik. Berbeda dari RDBMS besar lainnya, Postgres sendiri tidak memilikinya sebagai fitur bawaan, tetapi ada pola sederhana yang bisa dimanfaatkan sebagai fungsi SQL: https://github.com/nearform/temporal_tables
Anda bisa melihat keadaan tabel pada titik waktu tertentu, sehingga dapat menjawab pertanyaan seperti “apa pengaturan pengguna ini pada 12 Agustus?”, “berapa banyak record yang belum diproses pada pukul 23:55 tadi malam?”, atau “tunjukkan perbedaan feature flag saat ini dengan seminggu lalu”
Saya pernah berkonsultasi di sebuah perusahaan yang dulu memiliki SQL Server monolitik yang sangat besar. Memang bukan Postgres, tetapi anggap saja Postgres pun situasinya akan mirip
Selama puluhan tahun beroperasi, database itu dipakai untuk segala macam keperluan di dalam perusahaan, dan pada praktiknya semua aplikasi serta proses bisnis di seluruh perusahaan menyimpan data ke database ini
Masalahnya, ada banyak aplikasi yang membaca DB ini, dan ada sangat banyak proses serta prosedur yang menyisipkan dan mengubah data, sehingga ketika proses insert/update di hulu berubah atau ditambahkan, hal itu sampai melanggar invariant di level aplikasi. Proses yang normal pun berperilaku berbeda jika ada data yang buruk
Sangat sulit melacak penyebabnya, karena hal-hal yang diperiksa biasanya ditulis 10 tahun lalu dan para pegawainya sudah meninggalkan perusahaan
Saya penasaran apakah perubahan pada database Postgres bisa ditangkap dalam semacam bentuk DAG, sehingga kita bisa tahu proses mana yang menyisipkan, mengubah, atau menghapus data, bagaimana perilakunya secara historis, bagaimana berbagai aplikasi membaca data ini, dan bagaimana statistik kueri berubah seiring waktu
Saya tidak begitu tahu apakah ada preseden untuk ini, atau pendekatan seperti apa yang bisa dipakai untuk membuat alat semacam itu. Dulu saya pernah terpikir membuat sesuatu yang mirip, tetapi rasanya ini wilayah yang membutuhkan pemahaman setingkat engineer inti Postgres agar bisa membuat pilihan yang baik
Untuk setiap perubahan, Anda tidak mendapatkan data asal di level klien
Meski begitu, ada jalan memutar. Stream replikasi logis juga bisa memuat pesan informasi dari fungsi
pg_logical_emit_message, jadi klien dapat memasukkan metadata sendiri. Mungkin juga bisa dikonfigurasi agar identifier klien dipancarkan saat setiap transaksi dimulailast updated by). Bisa jadi ini antipattern, jadi akan bagus jika ada solusi yang lebih kokohPendekatan seperti ini bekerja pada hampir semua solusi keluarga SQL yang memakai WAL atau trigger
Di SQL Server, saya sudah beberapa kali memakai pendekatan trigger, tetapi jika semua kueri di-log, biasanya menjadi lambat. Merancang mekanisme insert yang tidak menghambat operasi produksi tidaklah sempurna, dan sampling mungkin diperlukan
Jika ingin mengambil jalur “tabel audit”, cukup pakai pgaudit. Ini ekstensi yang sudah teruji di praktik nyata, dan jika memakai AWS, juga bisa digunakan di RDS
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
Tidak perlu dilakukan. Menginginkan hal ini berarti mengubah relasi Postgres menjadi kontrak. Tidak ada layanan yang bisa mempersistenkan state internalnya
Jika benar-benar berkomitmen pada domain-driven design, mungkin saja bisa, tetapi lebih baik memakai sistem berbasis event yang ringan namun praktis
Sesuatu yang berbasis event 1000 kali lebih kompleks
Cara polling kolom
updated_attidak kokoh dalam bentuk yang paling sederhana. Sebab tidak ada jaminan transaksi akan commit dalam urutan ituupdated_atpada Row 1 disetel ke2023-09-22 12:00:01Tak lama kemudian transaksi B dimulai,
updated_atpada Row 2 disetel ke2023-09-22 12:00:02, dan B commit lebih duluKueri polling berjalan, melihat Row 2 sebagai perubahan terbaru lalu memperbarui cursor ke
2023-09-22 12:00:02; jika A kemudian commit belakangan, Row 1 akan terlewatCara sederhana untuk menghindari masalah ini adalah tidak melakukan polling nyaris real-time. Urutannya pada akhirnya akan menjadi konsisten
Saran yang lebih kokoh mungkin adalah memakai sequence. Misalnya membuat kolom
updated_at_idxyang bertambah setiap kali baris berubahSaya penasaran apakah dengan before trigger yang mengisi
now(), timestampupdated_atpada dua baris tetap bisa berbeda dari urutan commit transaksi.updated_atdan commit timestamp tidak harus sama, tetapiupdated_atharus merepresentasikan urutan commit secara akurat hingga level milidetik/mikrodetikupdated_at, gunakan kolom_txidyang disetel trigger ke ID transaksi saat ini. Lalu saat polling berikutnya, gunakantxid_current()untuk memeriksa transaksi mana yang sudah commit dan mana yang belumAgak riskan dan sangat mudah menimbulkan error di nilai batas, tetapi sudah berjalan baik di produksi selama beberapa tahun
Tulisannya bagus
Jika memakai Elixir dan Postgres, saya membuat library kecil dengan pendekatan serupa untuk mendengarkan perubahan WAL: https://github.com/cpursley/walex
Semua pendekatan ini agak kurang memuaskan, dan secara pribadi saya melihat polling sebagai yang paling praktis
Saya berharap Postgres berinovasi di area ini
Sebelum masuk ke standar SQL, menurut saya sulit muncul momentum di ruang kernel DBMS relasional. Opsinya banyak dan kompleks, sementara solusi yang berhasil di ruang pengguna pun umumnya tidak memberikan beban berlebihan dari sisi performa
Sebagai catatan, orang-orang yang meneliti bidang ini umumnya condong ke pendekatan tabel audit. Alasannya, pendekatan itu menjaga sifat ACID yang konsisten di dalam database, dan mempertahankan Postgres sebagai single point of failure alih-alih menambahkan proxy atau pekerjaan polling
Ada celah besar di dunia data. Alih-alih menanyakan hasil ke penyimpanan data, akan lebih baik jika hasil kueri didorong secara inkremental
Saya banyak melakukan analitik real-time dan streaming; pemrosesan stream bisa dilakukan, dan sebagian juga bisa ditangani sebagai materialized view di dalam penyimpanan data. Namun setelah data masuk ke DB atau data lake, untuk melihat perubahan di downstream pada dasarnya kita kembali lagi ke polling
Jika ingin bereaksi ketika kondisi tertentu terjadi di data, atau memperbarui layar tanpa refresh halaman, tidak banyak solusi yang rapi. Solusi dalam tulisan ini pun terlihat lebih seperti workaround daripada fitur kelas satu
Jika ingin membuat laporan yang diperbarui real-time tanpa refresh halaman, biasanya caranya adalah memuat data dari DB lalu mengalirkan perubahan ke GUI lewat Kafka dan WebSocket. Akibatnya kita mengoperasikan arsitektur lambda yang aneh, dengan sebagian analitik ditangani dalam kode dan sebagian di DB
Ada inovasi di area ini. KSQL dan Kafka Streams bisa mengeluarkan perubahan, Materialize punya subscription, dan ClickHouse punya live view. Namun banyak fiturnya masih baru atau tahap pratinjau dan tidak benar-benar pas. Saya sudah mencoba semuanya, tetapi rasanya terlalu banyak pekerjaan dilemparkan ke developer
Akan bagus jika ada library yang bisa langsung memberi feed perubahan lewat opsi seperti
[select * from orders with suscribe]. Ini area yang cukup penting, tetapi selama ini kurang mendapat perhatianAda jebakan besar pada replikasi yang tidak dibahas dalam tulisan itu, dan karena itulah saya tidak memakai replikasi
Postgres berusaha memberi jaminan yang sangat kuat agar konsumen slot replikasi tidak kehilangan data. Jadi jika konsumen tidak mengonsumsi data dari slot, Postgres dengan baik hati terus menyimpan data yang terlewat, sampai akhirnya disk penuh dan DB tumbang. Saya mengalaminya di dua DB SaaS berbeda saat prototyping, dan satu-satunya cara memulihkannya adalah membuat tiket dukungan
Jika konsumen slot replikasi berhenti membaca, alarm wajib berbunyi
Alasan lain adalah jalur kode untuk mengambil snapshot awal tabel dan jalur kode untuk membaca perubahan benar-benar berbeda. Menginisialisasi pembacaan slot replikasi agar tidak ada perubahan yang terlewat bukan hal sepele
Sayangnya, dari sudut pandang change capture, replikasi adalah solusi yang paling tidak terasa hacky
Saya memakai polling, tetapi menyimpan txid alih-alih
updated_atSaya penasaran perilaku seperti apa yang lebih Anda inginkan
Jika menangani volume data besar, snapshot awal dan pembacaan perubahan memang cenderung ingin diproses secara berbeda. Sebab kita perlu bisa melakukan hal-hal seperti inisialisasi paralel atau inisialisasi berbasis backup fisik. Meski begitu, saya paham bahwa fitur untuk men-stream data lama secara selektif setelah slot dibuat bisa berguna
Bagian menginisialisasi pembacaan slot replikasi agar perubahan tidak terlewat sepertinya tidak semestinya sulit; saya penasaran di bagian mana Anda tersangkut
Saat tidak membutuhkan semua perubahan, slot replikasi sementara yang membersihkan dirinya sendiri ketika koneksi terputus juga berguna. Ada juga konfigurasi untuk menetapkan batas maksimum WAL yang disimpan agar server tidak mati
Akan menarik kalau Anda bisa menjelaskan lebih lanjut bagaimana memakai txid alih-alih
updated_at