PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Cara Meningkatkan PostgreSQL 11 ke PostgreSQL 12 dengan Zero Downtime

Cara pemutakhiran basis data paling intuitif yang dapat Anda pikirkan adalah membuat replika dalam versi baru dan melakukan failover aplikasi ke dalamnya, dan sebenarnya itu berfungsi sempurna di mesin lain. Dengan PostgreSQL, ini dulunya tidak mungkin dengan cara asli. Untuk menyelesaikan peningkatan, Anda perlu memikirkan cara lain untuk meningkatkan, seperti menggunakan pg_upgrade, membuang dan memulihkan, atau menggunakan beberapa alat pihak ketiga seperti Slony atau Bucardo, semuanya memiliki peringatan sendiri. Ini karena cara PostgreSQL yang digunakan untuk mengimplementasikan replikasi.

Replikasi streaming PostgreSQL (replikasi PostgreSQL umum) adalah replikasi fisik yang mereplikasi perubahan pada tingkat byte demi byte, membuat salinan database yang identik di server lain. Metode ini memiliki banyak keterbatasan saat memikirkan peningkatan, karena Anda tidak dapat membuat replika di versi server yang berbeda atau bahkan dalam arsitektur yang berbeda.

Sejak PostgreSQL 10, ia telah menerapkan replikasi logis bawaan yang, berbeda dengan replikasi fisik, Anda dapat mereplikasi di antara berbagai versi utama PostgreSQL. Ini, tentu saja, membuka pintu baru untuk meningkatkan strategi.

Di blog ini, kita akan melihat bagaimana Anda dapat meningkatkan PostgreSQL 11 ke PostgreSQL 12 tanpa downtime menggunakan replikasi logis.

Replikasi Logis PostgreSQL

Replikasi logis adalah metode mereplikasi objek data dan perubahannya, berdasarkan identitas replikasinya (biasanya kunci utama). Ini didasarkan pada mode terbitkan dan berlangganan, di mana satu atau lebih pelanggan berlangganan satu atau lebih publikasi pada simpul penerbit.

Publikasi adalah kumpulan perubahan yang dihasilkan dari tabel atau grup tabel (juga disebut sebagai kumpulan replikasi). Node tempat publikasi didefinisikan disebut sebagai penerbit. Langganan adalah sisi hilir dari replikasi logis. Node di mana langganan didefinisikan disebut sebagai pelanggan, dan mendefinisikan koneksi ke database lain dan set publikasi (satu atau lebih) yang ingin berlangganan. Pelanggan mengambil data dari publikasi tempat mereka berlangganan.

Replikasi logis dibuat dengan arsitektur yang mirip dengan replikasi streaming fisik. Ini diimplementasikan oleh proses "walsender" dan "apply". Proses walsender memulai decoding logis dari WAL dan memuat plugin decoding logis standar. Plugin mengubah perubahan yang dibaca dari WAL ke protokol replikasi logis dan memfilter data sesuai dengan spesifikasi publikasi. Data kemudian terus ditransfer menggunakan protokol replikasi streaming ke pekerja yang menerapkan, yang memetakan data ke tabel lokal dan menerapkan perubahan individual saat diterima, dalam urutan transaksional yang benar.

Replikasi logis dimulai dengan mengambil snapshot data pada database penerbit dan menyalinnya ke pelanggan. Data awal dalam tabel langganan yang ada di-snapshot dan disalin dalam contoh paralel dari jenis proses penerapan khusus. Proses ini akan membuat slot replikasi sementara sendiri dan menyalin data yang ada. Setelah data yang ada disalin, pekerja memasuki mode sinkronisasi, yang memastikan bahwa tabel dibawa ke keadaan tersinkronisasi dengan proses penerapan utama dengan mengalirkan setiap perubahan yang terjadi selama penyalinan data awal menggunakan replikasi logis standar. Setelah sinkronisasi selesai, kontrol replikasi tabel diberikan kembali ke proses penerapan utama di mana replikasi berlanjut seperti biasa. Perubahan pada penerbit dikirim ke pelanggan saat terjadi secara real-time.

Cara Upgrade PostgreSQL 11 ke PostgreSQL 12 Menggunakan Replikasi Logis

Kita akan mengonfigurasi replikasi logis antara dua versi utama PostgreSQL (11 dan 12), dan tentu saja, setelah ini berfungsi, hanya masalah melakukan failover aplikasi ke dalam database dengan versi yang lebih baru.

Kami akan melakukan langkah-langkah berikut untuk membuat replikasi logis bekerja:

  • Konfigurasikan node penerbit
  • Konfigurasikan node pelanggan
  • Buat pengguna pelanggan
  • Buat publikasi
  • Buat struktur tabel di pelanggan
  • Buat langganan
  • Periksa status replikasi

Jadi, mari kita mulai.

Di sisi penerbit, kita akan mengonfigurasi parameter berikut di file postgresql.conf:

  • listen_addresses: Alamat IP mana yang akan didengarkan. Kami akan menggunakan '*' untuk semua.
  • wal_level: Menentukan berapa banyak informasi yang ditulis ke WAL. Kami akan menyetelnya ke "logis".
  • max_replication_slots :Menentukan jumlah maksimum slot replikasi yang dapat didukung server. Itu harus disetel ke setidaknya jumlah langganan yang diharapkan untuk terhubung, ditambah beberapa cadangan untuk sinkronisasi tabel.
  • max_wal_senders: Menentukan jumlah maksimum koneksi serentak dari server siaga atau klien cadangan basis streaming. Ini harus disetel setidaknya sama dengan max_replication_slots ditambah jumlah replika fisik yang terhubung pada saat yang sama.

Perlu diingat bahwa beberapa parameter ini memerlukan restart layanan PostgreSQL untuk diterapkan.

File pg_hba.conf juga perlu disesuaikan untuk memungkinkan replikasi. Anda harus mengizinkan pengguna replikasi untuk terhubung ke database.

Jadi berdasarkan ini, mari kita konfigurasikan publisher (dalam hal ini server PostgreSQL 11) sebagai berikut:

postgresql.conf:

listen_addresses = '*'

wal_level = logical

max_wal_senders = 8

max_replication_slots = 4

​pg_hba.conf:

# TYPE  DATABASE        USER            ADDRESS                 METHOD

host     all     rep1     10.10.10.131/32     md5

Anda harus mengubah pengguna (dalam contoh ini rep1), yang akan digunakan untuk replikasi, dan alamat IP 10.10.10.131/32 untuk IP yang sesuai dengan node PostgreSQL 12 Anda.

Di sisi pelanggan, ini juga membutuhkan max_replication_slots untuk disetel. Dalam hal ini, itu harus disetel ke setidaknya jumlah langganan yang akan ditambahkan ke pelanggan.

Parameter lain yang juga perlu diatur di sini adalah:

  • max_logical_replication_workers :Menentukan jumlah maksimum pekerja replikasi logis. Ini termasuk pekerja yang menerapkan dan pekerja sinkronisasi tabel. Pekerja replikasi logis diambil dari kumpulan yang ditentukan oleh max_worker_processes. Itu harus disetel ke setidaknya jumlah langganan, sekali lagi ditambah beberapa cadangan untuk sinkronisasi tabel.
  • max_worker_processes :Menyetel jumlah maksimum proses latar belakang yang dapat didukung sistem. Mungkin perlu disesuaikan untuk mengakomodasi pekerja replikasi, setidaknya max_logical_replication_workers + 1. Parameter ini memerlukan restart PostgreSQL.

Jadi, Anda harus mengkonfigurasi pelanggan (dalam hal ini server PostgreSQL 12) sebagai berikut:

postgresql.conf:

listen_addresses = '*'

max_replication_slots = 4

max_logical_replication_workers = 4

max_worker_processes = 8

Karena PostgreSQL 12 ini akan segera menjadi node utama baru, Anda harus mempertimbangkan untuk menambahkan parameter wal_level dan archive_mode dalam langkah ini, untuk menghindari restart baru layanan nanti.

wal_level = logical

archive_mode = on

Parameter ini akan berguna jika Anda ingin menambahkan replika baru atau menggunakan cadangan PITR.

Di penerbit, Anda harus membuat pengguna yang akan terhubung dengan pelanggan:

world=# CREATE ROLE rep1 WITH LOGIN PASSWORD '*****' REPLICATION;

CREATE ROLE

Peran yang digunakan untuk koneksi replikasi harus memiliki atribut REPLICATION. Akses untuk peran harus dikonfigurasi di pg_hba.conf dan harus memiliki atribut LOGIN.

Agar dapat menyalin data awal, peran yang digunakan untuk koneksi replikasi harus memiliki hak istimewa SELECT pada tabel yang dipublikasikan.

world=# GRANT SELECT ON ALL TABLES IN SCHEMA public to rep1;

GRANT

Kami akan membuat publikasi pub1 di node penerbit, untuk semua tabel:

world=# CREATE PUBLICATION pub1 FOR ALL TABLES;

CREATE PUBLICATION

Pengguna yang akan membuat publikasi harus memiliki hak istimewa CREATE dalam database, tetapi untuk membuat publikasi yang memublikasikan semua tabel secara otomatis, pengguna harus menjadi pengguna super.

Untuk mengonfirmasi publikasi yang dibuat, kami akan menggunakan katalog pg_publication. Katalog ini berisi informasi tentang semua publikasi yang dibuat dalam database.

world=# SELECT * FROM pg_publication;

-[ RECORD 1 ]+-----

pubname      | pub1

pubowner     | 10

puballtables | t

pubinsert    | t

pubupdate    | t

pubdelete    | t

pubtruncate  | t

Deskripsi kolom:

  • nama pub :Nama publikasi.
  • pemilik pub :Pemilik publikasi.
  • permainan bola :Jika benar, publikasi ini secara otomatis menyertakan semua tabel dalam database, termasuk yang akan dibuat di masa mendatang.
  • pubinsert :Jika benar, operasi INSERT direplikasi untuk tabel dalam publikasi.
  • pubupdate :Jika benar, operasi UPDATE direplikasi untuk tabel dalam publikasi.
  • hapus pub :Jika benar, operasi DELETE direplikasi untuk tabel dalam publikasi.
  • pubtruncate :Jika benar, operasi TRUNCATE direplikasi untuk tabel dalam publikasi.

Karena skema tidak direplikasi, Anda harus mengambil cadangan di PostgreSQL 11 dan memulihkannya di PostgreSQL 12 Anda. Cadangan hanya akan diambil untuk skema, karena informasi akan direplikasi di awal transfer.

Di PostgreSQL 11

$ pg_dumpall -s > schema.sql

Di PostgreSQL 12:

$ psql -d postgres -f schema.sql

Setelah Anda memiliki skema di PostgreSQL 12, Anda perlu membuat langganan, mengganti nilai host, dbname, pengguna, dan sandi dengan nilai yang sesuai dengan lingkungan Anda.

PostgreSQL 12:

world=# CREATE SUBSCRIPTION sub1 CONNECTION 'host=10.10.10.130 dbname=world user=rep1 password=*****' PUBLICATION pub1;

NOTICE:  created replication slot "sub1" on publisher

CREATE SUBSCRIPTION

Hal di atas akan memulai proses replikasi, yang menyinkronkan konten tabel awal dari tabel dalam publikasi dan kemudian mulai mereplikasi perubahan tambahan pada tabel tersebut.

Pengguna yang membuat langganan harus superuser. Proses penerapan langganan akan berjalan di database lokal dengan hak istimewa pengguna super.

Untuk memverifikasi langganan yang dibuat, Anda dapat menggunakan katalog pg_stat_subscription. Tampilan ini akan berisi satu baris per langganan untuk pekerja utama (dengan PID nol jika pekerja tidak berjalan), dan baris tambahan untuk pekerja yang menangani salinan data awal dari tabel langganan.

world=# SELECT * FROM pg_stat_subscription;

-[ RECORD 1 ]---------+------------------------------

subid                 | 16422

subname               | sub1

pid                   | 476

relid                 |

received_lsn          | 0/1771668

last_msg_send_time    | 2020-09-29 17:40:34.711411+00

last_msg_receipt_time | 2020-09-29 17:40:34.711533+00

latest_end_lsn        | 0/1771668

latest_end_time       | 2020-09-29 17:40:34.711411+00

Deskripsi kolom:

  • subid :OID langganan.
  • subname :Nama langganan.
  • pid :ID Proses dari proses pekerja langganan.
  • percaya :OID dari relasi yang disinkronkan oleh pekerja; null untuk pekerja lamaran utama.
  • received_lsn :Lokasi log write-ahead terakhir diterima, nilai awal bidang ini adalah 0.
  • last_msg_send_time :Waktu pengiriman pesan terakhir yang diterima dari pengirim WAL asal.
  • last_msg_receipt_time :Waktu penerimaan pesan terakhir yang diterima dari pengirim WAL asal.
  • latest_end_lsn :Lokasi log write-ahead terakhir dilaporkan ke pengirim WAL asal.
  • waktu_akhir_terbaru :Waktu dari lokasi log write-ahead terakhir yang dilaporkan ke pengirim WAL asal.

Untuk memverifikasi status replikasi di node utama, Anda dapat menggunakan pg_stat_replication:

world=# SELECT * FROM pg_stat_replication;

-[ RECORD 1 ]----+------------------------------

pid              | 527

usesysid         | 16428

usename          | rep1

application_name | sub1

client_addr      | 10.10.10.131

client_hostname  |

client_port      | 35570

backend_start    | 2020-09-29 17:40:04.404905+00

backend_xmin     |

state            | streaming

sent_lsn         | 0/1771668

write_lsn        | 0/1771668

flush_lsn        | 0/1771668

replay_lsn       | 0/1771668

write_lag        |

flush_lag        |

replay_lag       |

sync_priority    | 0

sync_state       | async

Deskripsi kolom:

  • pid :ID Proses dari proses pengirim WAL.
  • usesysid :OID pengguna yang masuk ke proses pengirim WAL ini.
  • namapengguna :Nama pengguna yang masuk ke proses pengirim WAL ini.
  • nama_aplikasi :Nama aplikasi yang terhubung dengan pengirim WAL ini.
  • client_addr :Alamat IP klien yang terhubung ke pengirim WAL ini. Jika bidang ini nol, ini menunjukkan bahwa klien terhubung melalui soket Unix di mesin server.
  • client_hostname :Nama host dari klien yang terhubung, seperti yang dilaporkan oleh pencarian DNS terbalik dari client_addr. Kolom ini hanya non-null untuk koneksi IP, dan hanya jika log_hostname diaktifkan.
  • client_port :nomor port TCP yang digunakan klien untuk komunikasi dengan pengirim WAL ini, atau -1 jika soket Unix digunakan.
  • backend_start :Waktu saat proses ini dimulai.
  • backend_xmin :Cakrawala xmin standby ini dilaporkan oleh hot_standby_feedback.
  • status :Status pengirim WAL saat ini. Nilai yang mungkin adalah:startup, catchup, streaming, backup, dan stop.
  • sent_lsn :Lokasi log write-ahead terakhir dikirim pada koneksi ini.
  • write_lsn :Lokasi log write-ahead terakhir yang ditulis ke disk oleh server siaga ini.
  • flush_lsn :Lokasi log write-ahead terakhir di-flush ke disk oleh server siaga ini.
  • replay_lsn :Lokasi log write-ahead terakhir diputar ulang ke database di server siaga ini.
  • write_lag :Waktu yang berlalu antara pembilasan WAL terbaru secara lokal dan penerimaan pemberitahuan bahwa server siaga ini telah menulisnya (tetapi belum membilas atau menerapkannya).
  • flush_lag :Waktu yang berlalu antara pembilasan WAL terbaru secara lokal dan penerimaan pemberitahuan bahwa server siaga ini telah menulis dan menghapusnya (tetapi belum menerapkannya).
  • replay_lag :Waktu yang berlalu antara pembilasan WAL terbaru secara lokal dan penerimaan pemberitahuan bahwa server siaga ini telah menulis, menghapus, dan menerapkannya.
  • sync_priority :Prioritas server siaga ini untuk dipilih sebagai siaga sinkron dalam replikasi sinkron berbasis prioritas.
  • sync_state :Status sinkron dari server siaga ini. Nilai yang mungkin adalah async, potential, sync, quorum.

Untuk memverifikasi kapan transfer awal selesai, Anda dapat memeriksa log PostgreSQL pada pelanggan:

2020-09-29 17:40:04.403 UTC [476] LOG:  logical replication apply worker for subscription "sub1" has started

2020-09-29 17:40:04.411 UTC [477] LOG:  logical replication table synchronization worker for subscription "sub1", table "city" has started

2020-09-29 17:40:04.422 UTC [478] LOG:  logical replication table synchronization worker for subscription "sub1", table "country" has started

2020-09-29 17:40:04.516 UTC [477] LOG:  logical replication table synchronization worker for subscription "sub1", table "city" has finished

2020-09-29 17:40:04.522 UTC [479] LOG:  logical replication table synchronization worker for subscription "sub1", table "countrylanguage" has started

2020-09-29 17:40:04.570 UTC [478] LOG:  logical replication table synchronization worker for subscription "sub1", table "country" has finished

2020-09-29 17:40:04.676 UTC [479] LOG:  logical replication table synchronization worker for subscription "sub1", table "countrylanguage" has finished

Atau periksa variabel srsubstate di katalog pg_subscription_rel. Katalog ini berisi status untuk setiap relasi yang direplikasi di setiap langganan.

world=# SELECT * FROM pg_subscription_rel;

 srsubid | srrelid | srsubstate | srsublsn

---------+---------+------------+-----------

   16422 |   16386 | r          | 0/1771630

   16422 |   16392 | r          | 0/1771630

   16422 |   16399 | r          | 0/1771668

(3 rows)

Deskripsi kolom:

  • srsubid :Referensi untuk berlangganan.
  • srrelid :Referensi ke relasi.
  • srsubstate :Kode keadaan:i =inisialisasi, d =data sedang disalin, s =disinkronkan, r =siap (replikasi normal).
  • srsublsn :Akhiri LSN untuk status s dan r.

Anda dapat menyisipkan beberapa catatan pengujian di PostgreSQL 11 dan memvalidasi bahwa Anda memilikinya di PostgreSQL 12:

PostgreSQL 11

world=# INSERT INTO city (id,name,countrycode,district,population) VALUES (5001,'city1','USA','District1',10000);

INSERT 0 1

world=# INSERT INTO city (id,name,countrycode,district,population) VALUES (5002,'city2','ITA','District2',20000);

INSERT 0 1

world=# INSERT INTO city (id,name,countrycode,district,population) VALUES (5003,'city3','CHN','District3',30000);

INSERT 0 1

PostgreSQL 12:

world=# SELECT * FROM city WHERE id>5000;

  id  | name  | countrycode | district  | population

------+-------+-------------+-----------+------------

 5001 | city1 | USA         | District1 |      10000

 5002 | city2 | ITA         | District2 |      20000

 5003 | city3 | CHN         | District3 |      30000

(3 rows)

Pada titik ini, Anda telah menyiapkan segalanya untuk mengarahkan aplikasi Anda ke PostgreSQL 12.

Untuk ini, pertama-tama, Anda perlu mengonfirmasi bahwa Anda tidak memiliki jeda replikasi.

Pada simpul utama:

world=# SELECT  application_name,  pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) lag FROM pg_stat_replication;

-[ RECORD 1 ]----+-----

application_name | sub1

lag              | 0

Dan sekarang, Anda hanya perlu mengubah endpoint dari aplikasi atau load balancer (jika ada) ke server PostgreSQL 12 yang baru.

Jika Anda memiliki penyeimbang beban seperti HAProxy, Anda dapat mengonfigurasinya menggunakan PostgreSQL 11 sebagai aktif dan PostgreSQL 12 sebagai cadangan, dengan cara ini:

Jadi, jika Anda mematikan simpul utama lama di PostgreSQL 11, server cadangan, dalam hal ini di PostgreSQL 12, mulai menerima lalu lintas secara transparan untuk pengguna/aplikasi.

Di akhir migrasi, Anda dapat menghapus langganan di node utama baru Anda di PostgreSQL 12:

world=# DROP SUBSCRIPTION sub1;

NOTICE:  dropped replication slot "sub1" on publisher

DROP SUBSCRIPTION

Dan verifikasi bahwa itu dihapus dengan benar:

world=# SELECT * FROM pg_subscription_rel;

(0 rows)

world=# SELECT * FROM pg_stat_subscription;

(0 rows)

Batasan

Sebelum menggunakan replikasi logis, harap perhatikan batasan berikut:

  • Skema database dan perintah DDL tidak direplikasi. Skema awal dapat disalin menggunakan pg_dump --schema-only.
  • Data urutan tidak direplikasi. Data dalam serial atau kolom identitas yang didukung oleh urutan akan direplikasi sebagai bagian dari tabel, tetapi urutan itu sendiri akan tetap menunjukkan nilai awal pada pelanggan.
  • Replikasi perintah TRUNCATE didukung, tetapi harus berhati-hati saat memotong grup tabel yang dihubungkan oleh kunci asing. Saat mereplikasi tindakan terpotong, pelanggan akan memotong grup tabel yang sama yang terpotong di penerbit, baik yang ditentukan secara eksplisit atau dikumpulkan secara implisit melalui CASCADE, dikurangi tabel yang bukan bagian dari langganan. Ini akan berfungsi dengan benar jika semua tabel yang terpengaruh adalah bagian dari langganan yang sama. Tetapi jika beberapa tabel yang akan dipotong pada pelanggan memiliki tautan kunci asing ke tabel yang bukan bagian dari langganan yang sama (atau apa pun), maka penerapan tindakan pemotongan pada pelanggan akan gagal.
  • Objek besar tidak direplikasi. Tidak ada solusi untuk itu, selain menyimpan data dalam tabel normal.
  • Replikasi hanya dimungkinkan dari tabel dasar ke tabel dasar. Artinya, tabel di publikasi dan di sisi langganan harus berupa tabel normal, bukan tampilan, tampilan terwujud, tabel akar partisi, atau tabel asing. Dalam hal partisi, Anda dapat mereplikasi hierarki partisi satu-ke-satu, tetapi saat ini Anda tidak dapat mereplikasi ke pengaturan yang dipartisi secara berbeda.

Kesimpulan

Menjaga server PostgreSQL Anda tetap mutakhir dengan melakukan pemutakhiran secara rutin merupakan tugas yang perlu tetapi sulit hingga versi PostgreSQL 10. Untungnya sekarang ini adalah cerita yang berbeda berkat replikasi logis.

Di blog ini kami membuat pengenalan singkat tentang replikasi logis, fitur PostgreSQL yang diperkenalkan secara asli di versi 10, dan kami telah menunjukkan kepada Anda bagaimana fitur ini dapat membantu Anda menyelesaikan peningkatan dari tantangan PostgreSQL 11 ke PostgreSQL 12 dengan strategi waktu henti nol.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Masukkan, pada pembaruan duplikat di PostgreSQL?

  2. Pendaftaran early bird dibuka untuk PGDay.IT 2011

  3. pg_restore Alternatif - Pencadangan PostgreSQL dan Pemulihan Otomatis dengan ClusterControl

  4. Periksa apakah NULL ada di array Postgres

  5. Membuat Modul Baru menggunakan PostgreSQL Create Extension