Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.
Menghindari masalah kinerja dengan REPLICA IDENTITY FULL di PostgreSQL RDS untuk PostgreSQL
Replikasi logis PostgreSQL mengharuskan setiap tabel yang diterbitkan memiliki identitas replika sehingga pelanggan dapat menemukan baris yang benar untuk diperbarui atau dihapus. Secara default, kunci utama berfungsi sebagai identitas replika. Ketika tabel tidak memiliki kunci primer atau indeks unik yang sesuai, Anda dapat mengatur identitas replikaFULL, yang menyebabkan PostgreSQL menggunakan seluruh baris sebagai kunci.
Sementara REPLICA IDENTITY FULL memecahkan masalah langsung mereplikasi tabel tanpa kunci utama, itu dapat memperkenalkan masalah kinerja yang serius pada penerbit dan pelanggan. Memahami dampak ini penting bagi siapa saja yang menggunakan replikasi logis dengan PostgreSQL RDS untuk PostgreSQL, termasuk fitur yang mengandalkan replikasi logis secara internal, seperti penerapan. blue/green
Mengapa REPLICA IDENTITY FULL menyebabkan masalah
Peningkatan volume WAL pada penerbit
REPLICA IDENTITYPengaturan mengontrol informasi apa yang ditulis PostgreSQL ke log write-ahead (WAL) untuk mengidentifikasi baris yang diperbarui atau dihapus. Dengan identitas replika default (kunci utama), hanya kolom kunci yang dicatat sebagai identitas baris lama. DenganFULL, PostgreSQL mencatat nilai-nilai lama dari setiap kolom untuk masing-masing dan. UPDATE DELETE Ini memiliki beberapa konsekuensi:
-
Ukuran WAL meningkat secara signifikan. Untuk pembaruan, ukuran setiap catatan WAL kira-kira dua kali lipat karena nilai lama dan baru untuk setiap kolom dicatat. Jika tabel berisi nilai besar yang disimpan menggunakan TOAST
, peningkatannya bisa jauh lebih besar karena nilai ToASted harus diambil dan ditulis ke WAL meskipun tidak dimodifikasi oleh pembaruan. -
Lebih tinggi I/O dan penggunaan CPU pada penerbit. Penulisan WAL tambahan mengkonsumsi lebih banyak I/O bandwidth disk dan siklus CPU, terutama untuk beban kerja berat tulis.
-
Lebih banyak data dikirim ke pelanggan. Penerbit harus mengirimkan catatan WAL yang lebih besar melalui jaringan ke setiap pelanggan, meningkatkan konsumsi bandwidth.
Pencarian baris lambat pada pelanggan
Ketika pelanggan menerima catatan UPDATE atau DELETE log, ia harus menemukan baris yang cocok dalam salinan tabel lokalnya. DenganREPLICA IDENTITY
FULL, pelanggan mencari baris yang cocok dengan semua nilai kolom dari gambar baris lama.
Bagaimana PostgreSQL melakukan pencarian ini berbeda dengan versi utama PostgreSQL:
-
Sebelum PostgreSQL 16: Jika tabel tidak memiliki kunci utama dan tidak ada indeks identitas replika yang dikonfigurasi secara eksplisit, pelanggan melakukan pemindaian sekuensial dari seluruh tabel untuk setiap satu atau operasi.
UPDATEDELETEPada tabel besar, ini membuat kinerja penerapan sangat lambat. -
PostgreSQL 16 dan yang lebih baru: Pelanggan dapat menggunakan btree atau indeks hash untuk pencarian baris, bahkan jika indeks tersebut tidak secara eksplisit ditetapkan sebagai identitas replika. Namun, pelanggan tidak mengevaluasi indeks mana yang paling efisien. Mulai versi 16
, PostgreSQL memilih indeks pertama yang cocok ditemukannya, dan pengguna tidak memiliki kendali atas pilihan ini. Jika indeks yang dipilih memiliki selektivitas rendah (misalnya, indeks pada kolom boolean atau status), pencarian baris bisa hampir sama lambatnya dengan pemindaian sekuensial. Untuk alasan ini, mengandalkan pemilihan indeks implisit dengan tidak dapat diandalkan dan harus dianggap sebagai fallback, REPLICA IDENTITY FULLbukan konfigurasi yang disarankan.
Bagaimana REPLICA IDENTITY FULL menyebabkan kelambatan replikasi
Dua masalah yang dijelaskan di atas — WAL yang lebih besar pada penerbit dan pencarian baris yang lebih lambat pada pelanggan — bergabung untuk menyebabkan kelambatan replikasi.
Secara default, replikasi logis PostgreSQL menggunakan proses apply worker tunggal per langganan untuk menerima perubahan dari penerbit dan menerapkannya ke tabel pelanggan. Proses apply worker berubah secara serial, satu baris pada satu waktu, dalam urutan komit. Ini berarti throughput pelanggan dibatasi oleh seberapa cepat ia dapat menerapkan setiap perubahan individu.
Ketika REPLICA IDENTITY FULL diatur di atas meja tanpa indeks yang sesuai, setiap UPDATE dan DELETE membutuhkan pemindaian sekuensial dari seluruh tabel untuk menemukan baris yang cocok. Jika tabel memiliki jutaan baris, masing-masing operasi ini dapat memakan waktu beberapa detik atau lebih lama. Hasilnya adalah masalah cascading:
-
Penerbit menghasilkan perubahan lebih cepat daripada yang dapat diterapkan pelanggan. Beban kerja penulisan penerbit berlanjut pada kecepatan normal, tetapi pekerja lamaran pelanggan terhambat pada pemindaian berurutan atau indeks selektif yang buruk untuk setiap pencarian baris.
-
WAL terakumulasi pada penerbit dan dapat menghabiskan penyimpanan. PostgreSQL tidak dapat merebut kembali segmen WAL sampai pelanggan mengonfirmasi telah menerapkannya. Ketika pelanggan tertinggal lebih jauh, penerbit mengakumulasi WAL pada disk. Pada , ini tampaknya tumbuh.
OldestReplicationSlotLagCloudWatch Dalam kasus yang parah, ini dapat menghabiskan semua penyimpanan yang tersedia dan menyebabkan penerbit berhenti menerima penulisan. -
Kelambatan itu memperkuat diri sendiri. Ketika pelanggan tertinggal, tabel pada pelanggan terus tumbuh dari sisipan yang direplikasi, membuat setiap pemindaian berurutan menjadi lebih lambat. Tanpa intervensi, lag tumbuh tanpa terikat.
Masalah ini sangat parah untuk tabel yang sering menerima UPDATE atau DELETE operasi. INSERToperasi tidak terpengaruh karena tidak memerlukan pencarian baris pada pelanggan.
catatan
Dimulai dengan PostgreSQL 16, apply worker dapat menggunakan parallel apply untuk transaksi streaming besar, yang dapat membantu throughput. Namun, hambatan pencarian baris mendasar untuk REPLICA IDENTITY FULL tanpa indeks tetap ada, karena setiap baris individu masih memerlukan pemindaian untuk menemukannya.
Dampak pada blue/green penerapan
Blue/green penerapan di Amazon Amazon RDS menggunakan replikasi logis secara internal untuk menjaga lingkungan hijau disinkronkan dengan lingkungan biru dengan menyiapkan satu langganan per database. Proses penerapan replikasi logis di lingkungan hijau adalah single-threaded. Proses pekerja terapkan tunggal menerima semua perubahan dari lingkungan biru dan menerapkannya satu per satu, dalam urutan komit. Tidak ada penerapan paralel di jalur blue/green replikasi.
Desain ulir tunggal ini berarti kemampuan lingkungan hijau untuk mengikuti lingkungan biru sepenuhnya bergantung pada seberapa cepat seseorang pekerja terapkan dapat memproses setiap perubahan individu. Ketika tabel digunakan REPLICA IDENTITY FULL tanpa kunci utama atau indeks yang sesuai, dampaknya pada pekerja terapan bergantung pada versi PostgreSQL. Dalam versi sebelum 16, setiap UPDATE dan DELETE pada tabel tersebut memaksa pekerja apply untuk melakukan pemindaian sekuensial dari seluruh tabel untuk menemukan baris yang cocok. Di versi 16 dan yang lebih baru, PostgreSQL akan menggunakan indeks yang sesuai
Konsekuensi untuk blue/green penyebaran sangat signifikan:
-
Kelambatan replikasi tumbuh terus menerus. Jika lingkungan biru menghasilkan lalu lintas tulis lebih cepat daripada yang dapat diproses oleh pekerja aplikasi tunggal, lingkungan hijau semakin tertinggal. Karena pekerja terapan berulir tunggal, tidak ada cara untuk memparalelkan pengejaran.
-
Switchover dapat diblokir. blue/green Peralihan membutuhkan lingkungan hijau untuk sepenuhnya disinkronkan dengan lingkungan biru. Jika kelambatan replikasi terlalu tinggi, peralihan tidak dapat diselesaikan dalam periode batas waktu.
-
Lingkungan hijau mungkin tidak akan pernah mengejar ketinggalan. Untuk beban kerja berat tulis dengan tabel besar menggunakan
REPLICA IDENTITY FULLdan tidak ada indeks, tingkat penerapan bisa sangat lambat sehingga lingkungan hijau tertinggal secara permanen, membuat peralihan tidak mungkin dilakukan tanpa terlebih dahulu menyelesaikan konfigurasi identitas replika. -
WAL terakumulasi di lingkungan biru. Sementara lingkungan hijau berada di belakang, lingkungan biru mempertahankan segmen WAL untuk slot replikasi. Hal ini meningkatkan penggunaan penyimpanan pada lingkungan biru (produksi) dan dapat mempengaruhi kinerja produksi.
Untuk menghindari masalah ini, pastikan bahwa semua tabel memiliki kunci utama atau indeks unik yang sesuai yang secara eksplisit dikonfigurasi sebagai identitas replika yang digunakan ALTER TABLE ... REPLICA
IDENTITY USING INDEX sebelum membuat penerapan. blue/green Jangan mengandalkan REPLICA IDENTITY FULL pemilihan indeks implisit di PostgreSQL 16+, karena pelanggan mungkin memilih indeks selektif yang buruk atau kembali ke pemindaian berurutan. Uji penerapan dengan beban kerja tulis yang representatif untuk mengonfirmasi bahwa lingkungan hijau dapat mengikuti.
Untuk informasi selengkapnya tentang batasan blue/green penerapan, lihatKeterbatasan dan pertimbangan untuk penerapan Amazon RDS Amazon blue/green. Untuk praktik terbaik, lihat RDS untuk PostgreSQL praktik terbaik untuk penerapan blue/green.
Cara mengidentifikasi tabel menggunakan REPLICA IDENTITY FULL
Jalankan kueri berikut untuk menemukan semua tabel denganREPLICA IDENTITY FULL:
SELECT n.nspname AS schema, c.relname AS table_name, c.relreplident FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = 'r' AND c.relreplident = 'f' AND n.nspname NOT IN ('pg_catalog', 'information_schema') ORDER BY n.nspname, c.relname;
Nilai relreplident kolom adalah:
d— default (kunci utama)n- tidak adaf— penuh (seluruh baris)i— indeks tertentu
Solusi dan praktik terbaik
Tambahkan kunci utama sedapat mungkin
Solusi paling efektif adalah menambahkan kunci utama ke tabel yang tidak memiliki satu. Ketika kunci utama ada, PostgreSQL menggunakannya sebagai identitas replika default, yang menyediakan pencarian baris yang efisien pada pelanggan dan meminimalkan overhead WAL pada penerbit.
ALTER TABLE my_table ADD COLUMN id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY;
penting
Pernyataan ini memperoleh ACCESS EXCLUSIVE kunci dan menulis ulang seluruh tabel, karena ekspresi nilai default menggunakan nextval() yang volatile. Semua membaca dan menulis ke tabel diblokir selama durasi penulisan ulang. Pada tabel besar, ini dapat menyebabkan downtime yang signifikan. Rencanakan perubahan ini selama jendela pemeliharaan atau pertimbangkan pendekatan alternatif seperti membuat kolom sebagai nullable terlebih dahulu, kemudian mengisi ulang dan menambahkan kendala dalam langkah terpisah.
Jika menambahkan kunci primer tidak layak karena kendala aplikasi, pertimbangkan untuk menambahkan indeks unik pada sekumpulan NOT NULL kolom dan mengaturnya sebagai identitas replika:
CREATE UNIQUE INDEX my_table_replica_idx ON my_table (col1, col2); ALTER TABLE my_table REPLICA IDENTITY USING INDEX my_table_replica_idx;
catatan
Untuk menghindari pemblokiran penulisan saat indeks dibuat, gunakan CONCURRENTLYCREATE UNIQUE INDEX CONCURRENTLY my_table_replica_idx ON my_table (col1,
col2);
catatan
Indeks yang digunakan untuk identitas replika harus unik, tidak boleh sebagian, tidak boleh ditangguhkan, dan harus menyertakan hanya kolom dengan batasan. NOT NULL
Jangan mengandalkan pemilihan indeks implisit (PostgreSQL 16+)
Dimulai dengan PostgreSQL 16, pekerja aplikasi pelanggan dapat menggunakan btree atau indeks hash untuk pencarian baris ketika identitas replika disetel FULL ke, bahkan jika indeks tersebut tidak secara eksplisit dikonfigurasi sebagai identitas replika. Meskipun ini mencegah pemindaian berurutan dalam beberapa kasus, mengandalkan perilaku implisit ini adalah anti-pola karena alasan berikut:
Anda tidak mengontrol indeks mana yang dipilih. PostgreSQL memilih indeks kualifikasi pertama yang ditemukan dalam urutan katalog, bukan yang paling selektif atau efisien. Jika tabel memiliki beberapa indeks kualifikasi, yang dipilih mungkin memiliki selektivitas rendah, yang menyebabkan kinerja pencarian buruk.
Perilakunya rapuh. Menambahkan, menjatuhkan, atau membangun kembali indeks dapat mengubah indeks mana yang digunakan pekerja aplikasi, yang berpotensi menyebabkan regresi kinerja yang tidak terduga dalam replikasi.
Ini menutupi masalah yang mendasarinya. Tabel tanpa kunci primer atau identitas replika eksplisit secara inheren berisiko untuk replikasi logis. Mengandalkan pemilihan indeks implisit menunda masalah daripada menyelesaikannya.
Sebagai gantinya, konfigurasikan identitas replika secara eksplisit untuk setiap tabel yang direplikasi:
Opsi terbaik: Tambahkan kunci utama. Ini adalah identitas replika yang paling andal dan efisien.
Alternatif: Gunakan
ALTER TABLE ... REPLICA IDENTITY USING INDEXuntuk menunjuk indeks unik, non-parsi, tidak dapat ditangguhkan tertentu dengan hanya kolom.NOT NULLIni memberi Anda kontrol eksplisit atas kolom mana yang digunakan untuk identifikasi baris.
Cadangan REPLICA IDENTITY FULL hanya untuk tabel di mana tidak ada opsi yang layak, dan pahami bahwa kinerja bergantung pada faktor-faktor di luar kendali langsung Anda.
Memantau kelambatan replikasi
Saat menggunakanREPLICA IDENTITY FULL, pantau kelambatan replikasi dengan cermat untuk mendeteksi pelambatan penerapan pelanggan sebelum menjadi kritis.
Pada penerbit, periksa jeda antara posisi WAL saat ini dan apa yang telah dikonfirmasi pelanggan:
SELECT slot_name, confirmed_flush_lsn, pg_current_wal_lsn(), (pg_current_wal_lsn() - confirmed_flush_lsn) AS lag_bytes FROM pg_replication_slots WHERE slot_type = 'logical';
lag_bytesNilai yang terus meningkat menunjukkan pelanggan tertinggal. pg_stat_replication_slotsTampilan memberikan statistik tambahan tentang penggunaan setiap slot replikasi.
Pada pelanggan, pg_stat_subscription tampilan menunjukkan status setiap pekerja yang mendaftar, termasuk lokasi WAL terakhir yang diterima dan dilaporkan:
SELECT subname, received_lsn, latest_end_lsn, last_msg_send_time, last_msg_receipt_time FROM pg_stat_subscription;
catatan
Pada PostgreSQL 16 dan yang lebih baru, Anda juga dapat worker_type memilih untuk membedakan antara pekerja aplikasi utama dan pekerja aplikasi paralel.
Kesenjangan besar antara received_lsn danlatest_end_lsn, atau stempel waktu basilast_msg_send_time, dapat mengindikasikan pekerja lamaran sedang berjuang untuk mengikutinya. pg_stat_subscription_statsTampilan juga melacak kesalahan dan konflik terapan yang mungkin menyebabkan kelambatan.
Untuk , Anda juga dapat memantau metrik, yang melacak lag dalam byte dari slot replikasi paling OldestReplicationSlotLag CloudWatch belakang. Nilai yang meningkat adalah tanda peringatan dini kelambatan replikasi.
Memeriksa tabel mana yang mungkin menggunakan indeks sub-optimal selama penerapan
Pada pelanggan, Anda dapat mengidentifikasi tabel tempat pekerja terapkan melakukan pembacaan heap yang berlebihan, yang dapat menunjukkan bahwa tabel tidak memiliki indeks yang efisien untuk pencarian baris selama penerapan. Jalankan kueri berikut pada pelanggan:
SELECT relname, heap_blks_read, heap_blks_hit, idx_blks_read, idx_blks_hit, heap_blks_read + heap_blks_hit AS total_heap_access FROM pg_statio_user_tables WHERE heap_blks_read > 0 ORDER BY heap_blks_read DESC LIMIT 10;
Tabel dengan heap_blks_read nilai relatif tinggi idx_blks_read dapat menunjukkan bahwa pekerja terapan tidak menggunakan indeks yang efisien untuk menemukan baris UPDATE dan DELETE operasi. Ini adalah sumber umum kelambatan replikasi saat REPLICA IDENTITY FULL digunakan.
catatan
Kueri ini membutuhkan track_counts
Evaluasi apakah REPLICA IDENTITY FULL diperlukan
Sebelum mengaturREPLICA IDENTITY FULL, pertimbangkan apakah Anda benar-benar membutuhkannya. Alasan umum untuk menggunakannya meliputi:
Tabel tidak memiliki kunci utama atau indeks unik.
Anda memerlukan gambar baris sebelum gambar lengkap untuk konsumen change data capture (CDC).
Anda memerlukan nilai kolom ToAasted yang disertakan dalam peristiwa replikasi untuk pembaruan yang tidak mengubah kolom tersebut.
Jika satu-satunya alasan Anda adalah kurangnya kunci utama, menambahkannya hampir selalu merupakan jalan yang lebih baik. Jika Anda memerlukan gambar sebelumnya lengkap untuk CDC, pertimbangkan apakah konsumen CDC Anda dapat merekonstruksi baris penuh dengan mempertahankan status secara eksternal, yang menghindari WAL dan overhead pelanggan. REPLICA IDENTITY FULL
Ringkasan rekomendasi
| Skenario | Rekomendasi |
|---|---|
| Tabel memiliki kunci utama | Gunakan identitas replika default (tidak perlu tindakan) |
| Tabel memiliki indeks NOT NULL yang unik | Tetapkan indeks itu sebagai identitas replika dengan ALTER TABLE ... REPLICA IDENTITY
USING INDEX |
| Tabel tidak memiliki kunci yang cocok (PostgreSQL 16+) | Tambahkan kunci primer atau indeks unik. Menggunakan REPLICA IDENTITY FULL dengan pemilihan indeks implisit tidak dapat diandalkan dan harus menjadi pilihan terakhir |
| Tabel tidak memiliki kunci yang cocok (sebelum PostgreSQL 16) | Tambahkan kunci primer atau indeks unik; hindari REPLICA IDENTITY FULL jika memungkinkan |
| Write-heavy beban kerja dengan kolom large/TOASTed | Hindari REPLICA IDENTITY FULL karena amplifikasi volume WAL |