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

Cara Meningkatkan PostgreSQL10 ke PostgreSQL11 Dengan Tanpa Waktu Henti

Secara historis, tugas tersulit ketika bekerja dengan PostgreSQL adalah berurusan dengan pemutakhiran. Cara pemutakhiran paling intuitif yang dapat Anda pikirkan adalah membuat replika dalam versi baru dan melakukan failover aplikasi ke dalamnya. Dengan PostgreSQL, ini tidak mungkin dilakukan 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.

Mengapa ini? Karena cara PostgreSQL mengimplementasikan replikasi.

Replikasi streaming bawaan PostgreSQL adalah apa yang disebut fisik:itu akan 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.

Jadi, di sinilah PostgreSQL 10 menjadi pengubah permainan. Dengan versi 10 dan 11 yang baru ini, PostgreSQL mengimplementasikan 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, mari kita lihat bagaimana kita dapat meningkatkan PostgreSQL 10 ke PostgreSQL 11 tanpa downtime menggunakan replikasi logis. Pertama-tama, mari kita melalui pengantar replikasi logis.

Apa itu Replikasi Logis?

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 dibangun 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.

Diagram Replikasi Logis

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.

Anda dapat menemukan lebih banyak tentang replikasi logis di blog berikut:

  • Ikhtisar Replikasi Logis di PostgreSQL
  • Replikasi Streaming PostgreSQL vs Replikasi Logis

Cara Upgrade PostgreSQL 10 ke PostgreSQL 11 Menggunakan Replikasi Logis

Jadi, setelah mengetahui tentang fitur baru ini, kami dapat memikirkan cara menggunakannya untuk menyelesaikan masalah peningkatan versi.

Kita akan mengonfigurasi replikasi logis antara dua versi utama PostgreSQL (10 dan 11), 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 menjalankan replikasi logis:

  • Konfigurasikan simpul 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 logika.
  • 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 bersamaan 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.

Ingatlah bahwa beberapa parameter ini memerlukan restart layanan PostgreSQL untuk diterapkan.

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

Jadi berdasarkan ini, mari kita konfigurasikan penerbit kita (dalam hal ini server PostgreSQL 10 kita) 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     rep     192.168.100.144/32     md5

Kami harus mengubah pengguna (dalam contoh perwakilan kami), yang akan digunakan untuk replikasi, dan alamat IP 192.168.100.144/32 untuk IP yang sesuai dengan PostgreSQL 11 kami.

Di sisi pelanggan, itu 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, kita harus mengkonfigurasi pelanggan kita (dalam hal ini server PostgreSQL 11 kita) sebagai berikut:

  • postgresql.conf:
    listen_addresses = '*'
    max_replication_slots = 4
    max_logical_replication_workers = 4
    max_worker_processes = 8

Karena PostgreSQL 11 ini akan segera menjadi master baru kami, kami 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 kita ingin menambahkan slave replikasi baru atau untuk menggunakan backup PITR.

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

world=# CREATE ROLE rep 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 rep;
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     | 16384
puballtables | t
pubinsert    | t
pubupdate    | t
pubdelete    | t

Deskripsi kolom:

  • namapub:Nama publikasi.
  • pemilik pub:Pemilik publikasi.
  • pubballtables: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.
  • pubdelete:Jika benar, operasi DELETE direplikasi untuk tabel dalam publikasi.

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

Di PostgreSQL 10:

$ pg_dumpall -s > schema.sql

Di PostgreSQL 11

$ psql -d postgres -f schema.sql

Setelah kami memiliki skema di PostgreSQL 11, kami membuat langganan, mengganti nilai host, dbname, pengguna, dan kata sandi dengan yang sesuai dengan lingkungan kami.

PostgreSQL 11

world=# CREATE SUBSCRIPTION sub1 CONNECTION 'host=192.168.100.143 dbname=world user=rep password=*****' PUBLICATION pub1;
NOTICE:  created replication slot "sub1" on publisher
CREATE SUBSCRIPTION

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

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

Untuk memverifikasi langganan yang dibuat, kita 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                 | 16428
subname               | sub1
pid                   | 1111
relid                 |
received_lsn          | 0/172AF90
last_msg_send_time    | 2018-12-05 22:11:45.195963+00
last_msg_receipt_time | 2018-12-05 22:11:45.196065+00
latest_end_lsn        | 0/172AF90
latest_end_time       | 2018-12-05 22:11:45.195963+00

Deskripsi kolom:

  • subid:OID langganan.
  • subname:Nama langganan.
  • pid:ID proses dari proses pekerja langganan.
  • relid: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.
  • latest_end_time:Waktu terakhir lokasi log write-ahead dilaporkan ke pengirim WAL asal.

Untuk memverifikasi status replikasi di master, kita dapat menggunakan pg_stat_replication:

world=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 1178
usesysid         | 16427
usename          | rep
application_name | sub1
client_addr      | 192.168.100.144
client_hostname  |
client_port      | 58270
backend_start    | 2018-12-05 22:11:45.097539+00
backend_xmin     |
state            | streaming
sent_lsn         | 0/172AF90
write_lsn        | 0/172AF90
flush_lsn        | 0/172AF90
replay_lsn       | 0/172AF90
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 ke 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:Horizon 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 dalam database di server siaga ini.
  • write_lag:Waktu yang berlalu antara mem-flush WAL terbaru secara lokal dan menerima pemberitahuan bahwa server siaga ini telah menulisnya (tetapi belum mem-flush atau menerapkannya).
  • flush_lag:Waktu yang berlalu antara pembilasan WAL terbaru secara lokal dan menerima pemberitahuan bahwa server siaga ini telah menulis dan menghapusnya (tetapi belum menerapkannya).
  • replay_lag:Waktu yang berlalu antara pembilasan WAL terbaru secara lokal dan menerima 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 kita dapat melihat log PostgreSQL pada pelanggan:

2018-12-05 22:11:45.096 UTC [1111] LOG:  logical replication apply worker for subscription "sub1" has started
2018-12-05 22:11:45.103 UTC [1112] LOG:  logical replication table synchronization worker for subscription "sub1", table "city" has started
2018-12-05 22:11:45.114 UTC [1113] LOG:  logical replication table synchronization worker for subscription "sub1", table "country" has started
2018-12-05 22:11:45.156 UTC [1112] LOG:  logical replication table synchronization worker for subscription "sub1", table "city" has finished
2018-12-05 22:11:45.162 UTC [1114] LOG:  logical replication table synchronization worker for subscription "sub1", table "countrylanguage" has started
2018-12-05 22:11:45.168 UTC [1113] LOG:  logical replication table synchronization worker for subscription "sub1", table "country" has finished
2018-12-05 22:11:45.206 UTC [1114] LOG:  logical replication table synchronization worker for subscription "sub1", table "countrylanguage" has finished

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

world=# SELECT * FROM pg_subscription_rel;
-[ RECORD 1 ]---------
srsubid    | 16428
srrelid    | 16387
srsubstate | r
srsublsn   | 0/172AF20
-[ RECORD 2 ]---------
srsubid    | 16428
srrelid    | 16393
srsubstate | r
srsublsn   | 0/172AF58
-[ RECORD 3 ]---------
srsubid    | 16428
srrelid    | 16400
srsubstate | r
srsublsn   | 0/172AF90

Deskripsi kolom:

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

Kami dapat memasukkan beberapa catatan pengujian di PostgreSQL 10 kami dan memvalidasi bahwa kami memilikinya di PostgreSQL 11

PostgreSQL 10:

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 11

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, kami telah menyiapkan segalanya untuk mengarahkan aplikasi kami ke PostgreSQL 11.

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

Pada master:

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, kita hanya perlu mengubah endpoint dari aplikasi atau load balancer (jika ada) ke server PostgreSQL 11 yang baru.

Jika kita memiliki load balancer seperti HAProxy, kita dapat mengkonfigurasinya menggunakan PostgreSQL 10 sebagai aktif dan PostgreSQL 11 sebagai cadangan, dengan cara ini:

HATampilan Status Proksi

Jadi, jika Anda baru saja mematikan master di PostgreSQL 10, server cadangan, dalam hal ini di PostgreSQL 11, mulai menerima lalu lintas secara transparan untuk pengguna/aplikasi.

Di akhir migrasi, kami dapat menghapus langganan di master baru kami di PostgreSQL 11

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)
Unduh Whitepaper Hari Ini Pengelolaan &Otomatisasi PostgreSQL dengan ClusterControlPelajari tentang apa yang perlu Anda ketahui untuk menerapkan, memantau, mengelola, dan menskalakan PostgreSQLUnduh Whitepaper

Batasan

Sebelum menggunakan replikasi logis, harap ingat 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 agar server PostgreSQL Anda tetap mutakhir dengan melakukan pemutakhiran secara rutin merupakan tugas yang perlu tetapi sulit hingga versi PostgreSQL 10.

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 tantangan ini dengan strategi tanpa waktu henti.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bisakah PostgreSQL memiliki batasan keunikan pada elemen array?

  2. Tipe data apa untuk garis lintang dan garis bujur?

  3. Bagaimana cara menonaktifkan integritas referensial di Postgres 8.2?

  4. Tidak dapat membuat layanan yang diminta [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]

  5. Pemeran tipe data Postgres