Migrasi yang mulus (hampir) antara rilis PostgreSQL besar menggunakan replikasi logis

Di True Engineering, pada satu proyek, kebutuhan telah datang untuk mengubah versi PostgreSQL dari 9.6 menjadi 11.1.

Mengapa Basis data pada proyek ini sudah berukuran 1,5 Tb dan terus bertambah. Kinerja adalah salah satu persyaratan utama untuk sistem. Dan struktur data itu sendiri berkembang: kolom baru ditambahkan, yang sudah ada diubah. Versi baru Postgres telah belajar cara bekerja secara efisien dengan penambahan kolom baru dengan nilai default, sehingga tidak perlu memagari kruk kustom di tingkat aplikasi. Bahkan dalam versi baru, beberapa cara baru tabel partisi ditambahkan, yang juga sangat berguna dalam kondisi sejumlah besar data.

Jadi, sudah diputuskan, kami sedang bermigrasi. Tentu saja, Anda dapat meningkatkan versi baru dari server PostgreSQL bersamaan dengan yang lama, menghentikan aplikasi, menggunakan dump / restore (atau pg_upgrade) untuk memindahkan database, dan memulai aplikasi lagi. Solusi ini tidak cocok untuk kami karena ukuran pangkalan yang besar, di samping itu, aplikasi berfungsi dalam mode pertempuran, dan hanya ada beberapa menit untuk downtime.

Oleh karena itu, kami memutuskan untuk mencoba migrasi menggunakan replikasi logis di PostgreSQL menggunakan plugin pihak ketiga yang disebut pglogical .

Dalam proses "percobaan", kami menemukan dokumentasi yang sangat terpisah tentang proses ini (dan dalam bahasa Rusia tidak sama sekali), serta beberapa jebakan dan nuansa yang tidak jelas. Pada artikel ini, kami ingin menyajikan pengalaman kami dalam bentuk Tutorial.



TL; DR

  • Semuanya ternyata (bukan tanpa kruk, artikel tentang mereka).
  • Anda dapat bermigrasi dalam versi PostgreSQL dari 9,4 ke 11.x, dari versi mana saja ke bawah, ke atas atau ke atas.
  • Waktu henti sama dengan waktu yang dibutuhkan aplikasi Anda untuk terhubung kembali ke server database baru (dalam kasus kami, itu adalah restart seluruh aplikasi, tetapi di alam liar, jelas, "opsi yang memungkinkan").

Mengapa solusi "dahi" tidak cocok untuk kita


Seperti yang telah kami katakan, jalan keluar yang paling mudah adalah menaikkan versi baru dari server PostgreSQL secara paralel dengan yang lama, menghentikan aplikasi, menggunakan dump / restore (atau pg_upgrade) untuk memindahkan database, dan memulai aplikasi lagi. Untuk database volume kecil, pada prinsipnya, ini adalah opsi yang cukup cocok (atau, dalam kasus umum, volume tidak penting ketika Anda memiliki opsi downtime aplikasi untuk periode "transfusi" database dari server lama ke yang baru, tidak peduli berapa lama waktu ini). Tetapi dalam kasus kami, basis data membutuhkan sekitar 1,5 Tb pada disk, dan memindahkannya bukan masalah beberapa menit, tetapi beberapa jam. Aplikasi ini, pada gilirannya, berfungsi dalam mode tempur, dan saya benar-benar ingin menghindari waktu henti selama lebih dari beberapa menit.

Juga terhadap opsi ini adalah kenyataan bahwa kami menggunakan replikasi Master-Slave dan tidak dapat dengan aman mematikan server Slave dari alur kerja. Jadi, untuk mengalihkan aplikasi dari versi PostgreSQL lama ke yang baru setelah migrasi dari server Master, perlu menyiapkan server Slave baru sebelum meluncurkan aplikasi. Dan ini adalah beberapa jam lagi downtime sampai Slave dibuat (walaupun jauh lebih sedikit daripada migrasi dari Master).

Oleh karena itu, kami memutuskan untuk mencoba migrasi menggunakan replikasi logis di PostgreSQL menggunakan plugin pihak ketiga yang disebut pglogical.

Informasi umum


pglogical adalah sistem replikasi logis menggunakan Decoding Logical asli dalam PostgreSQL dan diimplementasikan sebagai ekstensi PostgreSQL. Memungkinkan Anda mengonfigurasi replikasi selektif menggunakan model berlangganan / publikasi. Itu tidak memerlukan penciptaan pemicu dalam database atau penggunaan utilitas eksternal untuk replikasi.

Ekstensi berfungsi pada versi PostgreSQL apa pun, mulai dari 9,4 (sejak Decoding Logikal pertama kali muncul pada 9.4), dan memungkinkan Anda untuk bermigrasi di antara versi PostgreSQL yang didukung ke segala arah.

Menyiapkan replikasi secara manual menggunakan pglogical secara manual tidak terlalu sepele, meskipun pada prinsipnya sangat mungkin. Untungnya, ada pgrepup utilitas pihak ketiga untuk mengotomatisasi proses konfigurasi, yang akan kita gunakan.

Disk Space Memo


Karena kami berencana untuk meningkatkan versi baru PostgreSQL pada server yang sama secara paralel dengan yang lama, persyaratan disk untuk database pada server Master dan Slave menjadi dua kali lipat. Tampaknya ini sudah jelas, tapi ... Jaga cukup ruang kosong sebelum memulai replikasi, agar tidak menyesali tahun yang dihabiskan tanpa tujuan.

Dalam kasus kami, modifikasi database diperlukan, ditambah format penyimpanan selama migrasi antara 9,6 dan 11 "membengkak" tidak mendukung versi terbaru, sehingga ruang disk harus ditingkatkan bukan oleh 2, tetapi sekitar 2,2 kali. Puji LVM, ini bisa dilakukan dalam proses migrasi on the fly.

Secara umum, rawatlah itu.

Instal PostgreSQL 11 pada Master


Catatan: Kami menggunakan Oracle Linux, dan semua hal berikut akan dipertajam untuk distribusi ini. Ada kemungkinan bahwa distribusi Linux lainnya akan memerlukan sedikit revisi dengan sebuah file, tetapi sepertinya tidak akan signifikan.
#   yum install https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-7-x86_64/pgdg-oraclelinux11-11-2.noarch.rpm #   postgresql11 yum install postgresql11 postgresql11-devel postgresql11-server postgresql11-contrib #   /usr/pgsql-11/bin/postgresql-11-setup initdb 

Datadir lama terletak di /var/lib/pgsql/9.6/data , yang baru, oleh karena itu, ada di / var / lib / pgsql / 11 / data

Salin pengaturan akses ( pg_hba.conf ) dan pengaturan server ( postgresql.conf ) dari 9,6 ke 11.

Untuk menjalankan dua server PostgreSQL pada mesin yang sama, dalam konfigurasi konfigurasi postgresql.conf 11, ubah port menjadi 15432 (port = 15432).

Di sini Anda perlu berpikir hati-hati apa lagi yang perlu Anda lakukan dalam versi baru PostgreSQL khusus dalam kasus Anda, sehingga itu dimulai dengan postgresql.conf Anda (dan aplikasi Anda akhirnya dapat bekerja dengannya). Dalam kasus kami, diperlukan untuk menginstal ekstensi PostgreSQL yang digunakan oleh kami di versi baru. Ini di luar ruang lingkup artikel, buat saja PostgreSQL baru mulai, bekerja, dan sepenuhnya cocok untuk Anda :)

 #  ,  ,  shared libraries, whatever... # .... #  systemctl enable postgresql-11 systemctl start postgresql-11 

Kami mencari di / var / lib / pgsql / 11 / data / pg_log / . Apakah semuanya baik-baik saja? Kami melanjutkan!

Instal dan konfigurasikan pgrepup


 #  python yum install python yum install python2-pip #  pgrepup pip install pgrepup #   pgrepup config 



Nuansa:

  1. Sebagai app_owner kami menentukan pengguna yang menjalankan server PostgreSQL.
  2. Untuk Database, tentukan template1 .
  3. Nama Pengguna dan Kata Sandi - data untuk akses pengguna super. Dalam kasus kami, metode trust ditentukan dalam pg_hba.conf untuk koneksi lokal pengguna postgres , sehingga Anda dapat menentukan kata sandi secara sewenang-wenang.

Konfigurasikan Replikasi


 #   pgrepup check 

Kami mendapatkan output dari daftar banyak parameter yang harus dikonfigurasi sesuai kebutuhan.

Contoh hasil verifikasi:





Semua kesalahan selama verifikasi harus dihilangkan. Dalam pengaturan kedua server harus ditetapkan wal_level = LOGICAL (untuk Decoding Logical berfungsi), pengaturan yang diperlukan untuk mesin replikasi (jumlah slot dan wal_sender ). Petunjuk utilitas pgrepup cukup informatif; pertanyaan tidak boleh muncul pada sebagian besar poin.

Kami membuat semua pengaturan yang diperlukan yang diminta pgrepup.

Dalam kedua file pg_hba.conf kami menambahkan izin untuk pengguna yang akan melakukan replikasi, semua pada prompt pgrepup:

 host replication pgrepup_replication 127.0.0.1/32 md5 host all pgrepup_replication 127.0.0.1/32 md5 

Tambahkan Kunci Utama


Agar replikasi berfungsi, Kunci Utama harus didefinisikan di semua tabel.

Dalam kasus kami, PK tidak ada di mana-mana, oleh karena itu, pada saat replikasi, Anda perlu menambahkannya, dan pada akhir replikasi, jika perlu, hapus saja.

Daftar tabel tanpa PK, antara lain, menghasilkan pgrepup check . Untuk semua tabel dari daftar ini, Anda perlu menambahkan kunci utama dengan cara apa pun yang cocok untuk Anda. Dalam kasus kami, itu adalah sesuatu seperti:

 ALTER TABLE %s ADD COLUMN temporary_pk BIGSERIAL NOT NULL PRIMARY KEY 

Utilitas pgrepup memiliki perintah pgrepup fix untuk melakukan operasi ini ( pgrepup fix ), dan bahkan jika digunakan, diasumsikan bahwa jika replikasi berhasil, kolom sementara ini akan dihapus secara otomatis. Tapi, sayangnya, fungsi ini sangat ilusif dan mempesona buggy di pangkalan besar bahwa kami memutuskan untuk tidak menggunakannya, tetapi untuk melakukan operasi ini secara manual, karena nyaman bagi kami.

Instal ekstensi pglogical


Petunjuk untuk menginstal ekstensi dapat ditemukan di sini . Ekstensi harus diinstal di kedua server.

 #       curl https://access.2ndquadrant.com/api/repository/dl/default/release/9.6/rpm | bash curl https://access.2ndquadrant.com/api/repository/dl/default/release/11/rpm | bash #   yum install postgresql96-pglogical postgresql11-pglogical 

Tambahkan beban pustaka di postgresql.conf dari kedua server:

 shared_preload_libraries = 'pglogical' 

Pasang ekstensi pgl_ddl_deploy


Ini adalah ekstensi pembantu yang digunakan pgrepup untuk replikasi DDL logis.

 #      git clone https://github.com/enova/pgl_ddl_deploy.git #       PATH=/usr/pgsql-9.6/bin/:$PATH USE_PGXS=1 make USE_PGXS=1 make install make clean #       PATH=/usr/pgsql-11/bin/:$PATH make CLANG=true make install 

Tambahkan beban pustaka di postgresql.conf dari kedua server:

 shared_preload_libraries = 'pglogical,pgl_ddl_deploy' 

Memeriksa Perubahan


 #   postgresql systemctl restart postgresql-11 

Sekarang menggunakan pgrepup check Anda perlu memastikan bahwa semuanya telah menjadi baik-baik saja dengan server target dan semua komentar mengenai server target telah sepenuhnya dihilangkan.

Jika semuanya baik-baik saja, Anda dapat me-restart server lama. Di sini Anda perlu memikirkan bagaimana aplikasi Anda akan bereaksi terhadap restart server database, mungkin Anda harus menghentikannya terlebih dahulu.

 #  systemctl restart postgresql-9.6 #  pgrepup check 

Sekarang dalam output dari perintah, semua item harus ditandai sebagai OK.

Tampaknya Anda dapat memulai migrasi, tetapi ...

Perbaiki bug pgrepup


Ada beberapa bug dalam versi pgrepup saat ini yang membuat migrasi menjadi tidak mungkin. Permintaan penarikan telah dikirim, tetapi sayangnya, permintaan itu diabaikan, jadi Anda harus melakukan koreksi secara manual.

Kami pergi ke folder instalasi pgrepup (case kami adalah /usr/lib/python2.7/site-packages/pgrepup/commands/ ).

Lakukan sekali. Di setiap file * .py , tambahkan **kwargs hilang dalam deskripsi fungsi. Gambar lebih baik daripada seribu kata:



Berkomitmen di sini .

Lakukan dua. Di setup.py kita melakukan pencarian untuk "sh -c", dua entri, semua perintah shell multi-line harus dibuat satu-baris.

Berkomitmen di sini .

Mulai migrasi


 #  pgrepup setup 

Dengan perintah ini, pgrepup menyiapkan kedua server untuk memulai replikasi, membuat pengguna, mengkonfigurasi pglogical, mentransfer skema database.



 #   pgrepup start 

Dia berkata, "Ayo pergi!" dan melambaikan tangannya:



Replikasi sedang berjalan. Situasi saat ini dapat dilihat menggunakan perintah pgrepup status :



Di sini kita melihat bahwa dua database telah dipindahkan dan replikasi sedang berlangsung, dan satu masih dalam proses pemindahan. Sekarang tinggal minum kopi dan menunggu sampai seluruh volume database asli dipompa.

Sepanjang jalan, Anda dapat melihat lebih dalam ke fasad pgrepup dan melihat apa yang terjadi di bawah tenda. Untuk pikiran yang ingin tahu, berikut adalah daftar pertanyaan sebagai titik awal:

 SELECT * FROM pg_replication_origin_status ORDER BY remote_lsn DESC; SELECT *,pg_xlog_location_diff(s.sent_location,s.replay_location) byte_lag FROM pg_stat_replication s; SELECT query FROM pg_stat_activity WHERE application_name='subscription_copy' 

Memiliki banyak kopi (di server pengujian saat menulis artikel ini, migrasi ~ 700Gb data berlangsung sekitar satu hari), kami akhirnya melihat gambar berikut:



Dan itu berarti saatnya untuk mempersiapkan seorang budak baru.

Instal PostgreSQL 11 di Slave


Di sini semuanya sederhana dan menurut buku teks, tidak ada nuansa.

 #   yum install https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-7-x86_64/pgdg-oraclelinux11-11-2.noarch.rpm #  postgresql 11 yum install postgresql11 postgresql11-devel postgresql11-server postgresql11-contrib #      su - postgres pg_basebackup -h db-master.hostname -p 15432 -D /var/lib/pgsql/11/data/ -R -P -U replication -X stream -c fast 

Salin pengaturan akses ( pg_hba.conf ) dan pengaturan server ( postgresql.conf ) dari 9,6 ke 11. Dalam konfigurasi versi postgresql.conf 11, ubah port ke 15432 (port = 15432)

 #  systemctl enable postgresql-11 systemctl start postgresql-11 

 #     Master SELECT *,pg_wal_lsn_diff(s.sent_lsn,s.replay_lsn) AS byte_lag FROM pg_stat_replication s; #     Slave SELECT now()-pg_last_xact_replay_timestamp(); 

Subtotal


Setelah semua prosedur ini, kami mendapatkan skema replikasi yang rumit ini:



Di sini, sebagai cek terakhir (dan, pada akhirnya, itu hanya indah), Anda dapat melakukan beberapa PEMBARUAN di database Master 9.6 dan melihat bagaimana itu direplikasi ke tiga server lainnya.

gambar

Mengalihkan aplikasi ke versi baru PostgreSQL


Sejauh ini, aplikasi kami belum mencurigai adanya versi baru PostgreSQL, saatnya untuk memperbaikinya. Opsi di sini pada dasarnya bergantung hanya pada dua hal:
Apakah Anda akan melebihi layanan baru pada port yang sama di mana yang lama bekerja,
dan apakah aplikasi Anda memerlukan restart ketika memulai kembali server database.

Untuk bersenang-senang, kami akan menjawab kedua pertanyaan "ya" dan melanjutkan.

Kami menghentikan aplikasi.

 # ,   , : SELECT * FROM pg_stat_activity; 

 #    #       sequences. pgrepup stop 



 #      pgrepup uninstall 



 #  master: #    systemctl disable postgresql-9.6 #   ,  ,  . systemctl stop postgresql-9.6 systemctl stop postgresql-11 #  slave: #    systemctl disable postgresql-9.6 #   ,  ,  . systemctl stop postgresql-9.6 systemctl stop postgresql-11 

Kami mengembalikan port standar di konfigurasi postgresql.conf versi baru ke Master dan Slave.

Pada Slave baru, kami juga mengubah port ke yang standar di recovery.conf .

Sepanjang jalan, ada saran dari dosa untuk lebih lanjut mengubah port pada versi lama menjadi tidak aktif:
Kami mengekspos port non-standar di postgresql.conf dari versi lama ke Master dan Slave.
Pada Slave lama, kami juga mengubah port ke yang non-standar di recovery.conf .

 #   master systemctl enable postgresql-11 systemctl start postgresql-11 #   slave: systemctl enable postgresql-11 systemctl start postgresql-11 

Periksa log.

Periksa status replikasi pada Master.

 SELECT *,pg_wal_lsn_diff(s.sent_lsn,s.replay_lsn) AS byte_lag FROM pg_stat_replication s; 

Kami meluncurkan aplikasi. Kami senang selama setengah jam.

Dan akhirnya, literatur yang bermanfaat tentang topik:


Semoga beruntung

Source: https://habr.com/ru/post/id437318/


All Articles