Kamis, 18 Juli 2024

POSTGRES-backup restore wal

 

https://www.highgo.ca/2020/10/01/postgresql-wal-archiving-and-point-in-time-recovery/

Pengarsipan WAL PostgreSQL dan Pemulihan Point-In-Time

WAL adalah kependekan dari Write-Ahead-Log. Setiap perubahan pada data pertama-tama dicatat dalam file WAL. File WAL terutama digunakan oleh RDBMS sebagai cara untuk mencapai ketahanan dan konsistensi saat menulis data ke sistem penyimpanan.

Sebelum kita melanjutkan, mari kita lihat dulu mengapa kita memerlukan pengarsipan WAL dan Point in Time Recovery (PITR). Pertimbangkan apakah Anda secara tidak sengaja menjatuhkan beberapa tabel atau menghapus beberapa data? Bagaimana cara Anda pulih dari kesalahan seperti itu? Pengarsipan WAL dan PITR adalah jawabannya. File WAL dapat diputar ulang di server untuk membuat ulang perubahan yang direkam di server itu. Oleh karena itu kita dapat menggunakan WAL untuk pulih dari situasi berbahaya tersebut. Sedangkan PITR adalah cara untuk menghentikan pemutaran ulang WAL pada titik yang ditentukan dan memiliki snapshot data yang konsisten pada saat itu. yaitu sesaat sebelum tabel dihilangkan atau data dihapus.

Cara Melakukan Pengarsipan WAL

Biasanya, database PostgreSQL menyimpan file WAL di direktori pg_wal dari $PGDATA. Namun, file WAL ini mungkin didaur ulang dan dapat dihapus/ditimpa oleh server. Jadi untuk menghindari skenario seperti itu, kami menyimpan salinan file WAL di direktori terpisah selain $PGDATA.
Untuk melakukan itu, server PostgreSQL memberi kita cara untuk menyalin file WAL ke lokasi lain segera setelah file WAL dibuat oleh server. Cara ini bergantung pada tiga perintah (opsi) yaitu archive_mode , archive_command , dan wal_level. Opsi ini dapat diatur di file konfigurasi $PGDATA/postgresql.conf.

Opsi Pengarsipan

Server PostgreSQL memberi kita beberapa opsi yang dapat digunakan untuk mengontrol pengarsipan WAL. Mari kita lihat apa saja opsi-opsi ini dan bagaimana menggunakannya.

  • archive_mode menandakan apakah kita ingin mengaktifkan pengarsipan WAL. Itu dapat menerima nilai-nilai berikut:
    • aktif – untuk mengaktifkan pengarsipan
    • mati – menonaktifkan pengarsipan
    • selalu – biasanya opsi ini sama dengan 'aktif'. Ini juga memungkinkan pengarsipan untuk server siaga. Jika standby berbagi jalur yang sama dengan server lain, hal ini dapat menyebabkan kerusakan file WAL. Jadi kehati-hatian harus diberikan dalam kasus ini.
  • archive_command menentukan cara mengarsipkan (menyalin) file WAL dan di mana. Opsi ini menerima perintah shell atau skrip shell. Yang dijalankan setiap kali ada file WAL yang dihasilkan oleh server untuk mengarsipkannya. Opsi ini menerima placeholder berikut:
    • %f – jika ada diganti dengan nama file dari file WAL.
    • %p – jika ada diganti dengan nama path file WAL.
    • %% – diganti dengan '%'
  • wal_level adalah opsi penting lainnya. Di PostgreSQL versi 10+, defaultnya adalah 'replika', sebelum versi ini disetel ke minimal secara default. wal_level menerima nilai-nilai berikut:
    • Minimal – hanya menambahkan informasi yang diperlukan untuk pemulihan kerusakan atau dari penghentian langsung. Itu tidak dapat digunakan untuk tujuan replikasi atau pengarsipan.
    • Replika – menandakan bahwa WAL akan memiliki informasi yang cukup untuk pengarsipan dan replikasi WAL.
    • Logis – menambahkan informasi yang diperlukan untuk replikasi logis.
contoh arsip wal.
vim $PGDATA/postgresql. konf
archive_mode = aktif
archive_command = 'cp %p /path/t o//archive_dir/%f'
wal_level = replika

Pemulihan Titik Dalam Waktu

Di PostgreSQL, PITR adalah cara untuk menghentikan pemutaran ulang file WAL pada waktu yang tepat. Mungkin terdapat banyak file WAL dalam arsip tetapi kami mungkin tidak ingin memutar ulang semuanya. Memutar ulang semua WAL akan menghasilkan keadaan yang sama dimana kita melakukan beberapa kesalahan. Ada dua prasyarat penting yang diperlukan agar PITR dapat berfungsi.

  • Ketersediaan cadangan basis penuh (biasanya diambil dengan pg_basebackup)
  • File WAL (arsip WAL)

Untuk mencapai PITR, langkah pertama adalah memulihkan cadangan dasar yang diambil sebelumnya dan kemudian membuat pengaturan pemulihan. Penyiapan memerlukan konfigurasi opsi recovery_command dan recovery_target .

  • recovery_command menentukan dari mana mencari file WAL untuk diputar ulang di server ini. Perintah ini menerima placeholder yang sama dengan archive_command.
  • recovery_target_time Opsi ini memberitahu server kapan harus menghentikan proses pemulihan atau pemutaran ulang. Proses akan berhenti segera setelah stempel waktu yang ditentukan tercapai.

recovery_target_inclusive Opsi ini mengontrol apakah akan menghentikan pemutaran ulang WAL tepat setelah waktu_target_pemulihan tercapai (jika disetel ke benar) atau tepat sebelum (jika disetel ke salah).

contoh opsi pemulihan PITR.
vim $BACKUP/postgresql. menipu
recovery_command = 'cp /path/t o//archive_dir/%f %p'
waktu_target_pemulihan = ''
recovery_target_inclusive = salah

Demo

Mari gabungkan semua hal di atas dalam demonstrasi praktis dan lihat cara kerjanya.

# Mulai server
./pg_ctl -D $PGDATA mulai
# ambil cadangan basis
./pg_basebackup -D $BACKUP -Fp
# sambungkan dan masukkan beberapa data
./psql postgres
postgres =# buat tabel foo(c1 int, c2 stempel waktu default stempel waktu saat ini);
BUAT TABEL
postgres =# masukkan ke foo pilih generate_series(1, 1000000), clock_timestamp();
MASUKKAN 0 1000000
postgres =# pilih cap waktu_saat ini;
stempel waktu_saat ini
-------------------------------
2020 - 10 - 01 18 : 01 : 18.157764 + 05
( 1 baris )
postgres =# hapus dari foo;
HAPUS 1000000
postgres =# pilih cap waktu_saat ini;
stempel waktu_saat ini
-------------------------------
2020 - 10 - 01 18 : 01 : 36.272033 + 05
( 1 baris )

Mari kita hentikan server dan buat pengaturan pemulihan pada cadangan untuk dihentikan sebelum penghapusan data terjadi.

./pg_ctl -D $PGDATA berhenti
# beri tahu cluster ini untuk memulai mode pemulihan.
sentuh $BACKUP/pemulihan. sinyal
# edit file konfigurasi untuk mengatur opsi pemulihan pada cluster cadangan.
vim $BACKUP/postgresql. konf
# Opsi Pemulihan
recovery_command = 'cp $HOME/wal_archive/%f %p'
waktu_target_pemulihan = ' 2020 - 10 - 01 18 : 01 : 18.157764 + 05 '
recovery_target_inclusive = salah
# mari mulai cluster pencadangan dan mulai proses pemulihan.
./pg_ctl -D $BACKUP mulai
2020 - 10 - 01 18 : 03 : 17.365 PKT [ 71219 ] LOG: mendengarkan pada alamat IPv4 "127.0.0.1" , port 5432
2020 - 10 - 01 18 : 03 : 17.366 PKT [ 71219 ] LOG: mendengarkan pada soket Unix "/tmp/.s.PGSQL.5432"
2020 - 10 - 01 18 : 03 : 17.371 PKT [ 71220 ] LOG: sistem database terganggu; terakhir diketahui pada 2020 - 10 - 01 18 : 00 : 45 PKT
2020 - 10 - 01 18 : 03 : 17.413 PKT [ 71220 ] LOG: titik awal pemulihan tepat waktu hingga 2020 - 10 - 01 18 : 01 : 18.157764 + 05
2020 - 10 - 01 18 : 03 : 17.441 PKT [ 71220 ] LOG: memulihkan file log "000000010000000000000002" dari arsip
2020 - 10 - 01 18 : 03 : 17.463 PKT [ 71220 ] LOG: pengulangan dimulai pada 0/2000028
2020 - 10 - 01 18 : 03 : 17.463 PKT [ 71220 ] LOG: status pemulihan konsisten tercapai pada 0/2000100
2020 - 10 - 01 18 : 03 : 17.463 PKT [ 71219 ] LOG: sistem database siap menerima koneksi hanya baca
2020 - 10 - 01 18 : 03 : 17.501 PKT [ 71220 ] LOG: memulihkan file log "000000010000000000000003" dari arsip
2020 - 10 - 01 18 : 03 : 18.182 PKT [ 71220 ] LOG: memulihkan file log "000000010000000000000004" dari arsip
2020 - 10 - 01 18 : 03 : 18.851 PKT [ 71220 ] LOG: memulihkan file log "000000010000000000000005" dari arsip
2020 - 10 - 01 18 : 03 : 19.539 PKT [ 71220 ] LOG: memulihkan file log "000000010000000000000006" dari arsip
2020 - 10 - 01 18 : 03 : 20.195 PKT [ 71220 ] LOG: memulihkan file log "000000010000000000000007" dari arsip
2020 - 10 - 01 18 : 03 : 20.901 PKT [ 71220 ] LOG: memulihkan file log "000000010000000000000008" dari arsip
2020 - 10 - 01 18 : 03 : 21.574 PKT [ 71220 ] LOG: memulihkan file log "000000010000000000000009" dari arsip
2020 - 10 - 01 18 : 03 : 22.286 PKT [ 71220 ] LOG: memulihkan file log "00000001000000000000000A" dari arsip
2020 - 10 - 01 18 : 03 : 22.697 PKT [ 71220 ] LOG: pemulihan terhenti sebelum transaksi dilakukan 508 , waktu 2020 - 10 - 01 18 : 01 : 32.304189 + 05
2020 - 10 - 01 18 : 03 : 22.697 PKT [ 71220 ] LOG : jeda di akhir pemulihan
2020 - 10 - 01 18 : 03 : 22.697 PKT [ 71220 ] PETUNJUK: Jalankan pg_wal_replay_resume () untuk melakukan promosi.

Hubungkan ke cluster ini dan lihat apakah kita masih memiliki data di tabel foo?

postgres =# pilih hitungan(*) dari foo;
menghitung
---------
1000000
( 1 baris )

Lihat ketika pemulihan berhenti, kami masih memiliki datanya!

Kesimpulan

PITR adalah proses penting untuk memulihkan data penting jika terjadi kerusakan server yang dapat mengakibatkan direktori data tidak valid/rusak yang menyebabkan downtime. Namun yang bisa dicegah adalah dampak crash yang mengakibatkan hilangnya data. 

Menyimpan cadangan penuh terkini dengan file WAL akan menghasilkan proses pemulihan yang sederhana dan nyaman. Waktu pemulihan akan bergantung pada seberapa baru pencadangan penuh dilakukan dan berapa banyak file WAL yang dihasilkan setelah pencadangan tersebut.

===========================

PostgreSQL WAL Archiving and Point-In-Time-Recovery

WAL is short for Write-Ahead-Log. Any change to the data is first recorded in a WAL file. The WAL files are mainly used by RDBMS as a way to achieve durability and consistency while writing data to storage systems.

Before we move forward, let’s first see why we need a WAL archiving and Point in Time Recovery (PITR). Consider if you have accidentally dropped some table(s) or deleted some data? How do you recover from such mistakes? WAL archiving and PITR is the answer to that. A WAL file can be replayed on a server to recreate the recorded changes on that server. Hence we can use the WALs to recover from such dangerous situations. Whereas the PITR is a way to stop the replay of WALs at the specified point and have a consistent snapshot of data at that time. i.e. just before the table is dropped or data is removed.

How to Perform WAL Archiving

Normally, PostgreSQL databases keep the WAL files in the pg_wal directory of the $PGDATA. However, these WAL files may get recycled and can be deleted/overwritten by the server. So to avoid such scenarios, we keep a copy of WAL files in a separate directory other than $PGDATA.
In order to do that, the PostgreSQL server provides us a way to copy the WAL file to a different location as soon as a WAL file is generated by the server. This way depends on three commands (options) namely archive_modearchive_command, and wal_level. These options can be set in the $PGDATA/postgresql.conf configuration file.

Archiving Options

PostgreSQL server provides us with some options through which we can control the WAL archiving. Let’s see what these options are and how to use them.

  • archive_mode signifies whether we want to enable the WAL archiving. It can accept the following values:
    • on – to enable the archiving
    • off – disable the archiving
    • always – normally this option is the same as ‘on’. This enables archiving for a standby server as well. If the standby shares the same path with another server, it may lead to WAL file corruption. So care must be taken in this case.
  • archive_command specifies how to archive (copy) the WAL files and where. This option accepts the shell command or a shell script. Which is executed whenever there is a WAL file generated by the server to archive it. This option accepts the following placeholders:
    • %f – if present it’s replaced with the filename of the WAL file.
    • %p – if present it is replaced with the pathname of the WAL file.
    • %% – is replaced with ‘%’
  • wal_level is another important option. In PostgreSQL version 10+, it defaults to ‘replica’, prior to this version it was set to minimal by default. wal_level accepts the following values:
    • Minimal – adds only the information that is required for crash recovery or from immediate shutdown. It’s not usable for replication or archiving purposes.
    • Replica – signifies that WAL will have enough information for WAL archiving and replication.
    • Logical – adds information required for logical replication.
an example of wal archive.
vim $PGDATA/postgresql.conf
archive_mode = on
archive_command = ‘cp %p /path/to//archive_dir/%f’
wal_level = replica

Point In Time Recovery

In PostgreSQL, PITR is a way to stop the replay of WAL files at an appropriate point in time. There can be many WAL files in the archive but we may not want to replay all of them. Replaying all WALs will result in the same state where we had made some mistake. There are two important prerequisites required for PITR to work.

  • Availability of a full base backup (usually taken with pg_basebackup)
  • WAL files (WAL archive)

In order to achieve the PITR, the first step would be to restore an earlier taken base backup and then create a recovery setup. The setup requires configuring restore_command and recovery_target options.

  • restore_command specifies from where to look up the WAL files to replay on this server. This command accepts the same placeholders as archive_command.
  • recovery_target_time This option tells the server when to stop the recovery or replay process. The process will stop as soon as the given timestamp is reached.

recovery_target_inclusive This option controls whether to stop the replay of WALs just after the recovery_target_time is reached (if set to true) or just before (if set to false).

an example of PITR recovery options.
vim $BACKUP/postgresql.con
restore_command = ‘cp /path/to//archive_dir/%f %p’
recovery_target_time = ‘’
recovery_target_inclusive = false

Demo

Let’s combine all of the above in a practical demonstration and see how this all works.

# Start server
./pg_ctl -D $PGDATA start
# take a base backup
./pg_basebackup -D $BACKUP -Fp
# connect and put some data
./psql postgres
postgres=# create table foo(c1 int, c2 timestamp default current_timestamp);
CREATE TABLE
postgres=# insert into foo select generate_series(1, 1000000), clock_timestamp();
INSERT 0 1000000
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2020-10-01 18:01:18.157764+05
(1 row)
postgres=# delete from foo;
DELETE 1000000
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2020-10-01 18:01:36.272033+05
(1 row)

Let’s stop the server and create a recovery setup on the backup to stop before the deletion of data occurred.

./pg_ctl -D $PGDATA stop
# tell this cluster to start on recovery mode.
touch $BACKUP/recovery.signal
# edit configuration file to setup recovery options on the backup cluster.
vim $BACKUP/postgresql.conf
# Recovery Options
restore_command = ‘cp $HOME/wal_archive/%f %p’
recovery_target_time = ‘2020-10-01 18:01:18.157764+05
recovery_target_inclusive = false
# let’s start the backup cluster and start the recovery process.
./pg_ctl -D $BACKUP start
2020-10-01 18:03:17.365 PKT [71219] LOG: listening on IPv4 address "127.0.0.1", port 5432
2020-10-01 18:03:17.366 PKT [71219] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432"
2020-10-01 18:03:17.371 PKT [71220] LOG: database system was interrupted; last known up at 2020-10-01 18:00:45 PKT
2020-10-01 18:03:17.413 PKT [71220] LOG: starting point-in-time recovery to 2020-10-01 18:01:18.157764+05
2020-10-01 18:03:17.441 PKT [71220] LOG: restored log file "000000010000000000000002" from archive
2020-10-01 18:03:17.463 PKT [71220] LOG: redo starts at 0/2000028
2020-10-01 18:03:17.463 PKT [71220] LOG: consistent recovery state reached at 0/2000100
2020-10-01 18:03:17.463 PKT [71219] LOG: database system is ready to accept read only connections
2020-10-01 18:03:17.501 PKT [71220] LOG: restored log file "000000010000000000000003" from archive
2020-10-01 18:03:18.182 PKT [71220] LOG: restored log file "000000010000000000000004" from archive
2020-10-01 18:03:18.851 PKT [71220] LOG: restored log file "000000010000000000000005" from archive
2020-10-01 18:03:19.539 PKT [71220] LOG: restored log file "000000010000000000000006" from archive
2020-10-01 18:03:20.195 PKT [71220] LOG: restored log file "000000010000000000000007" from archive
2020-10-01 18:03:20.901 PKT [71220] LOG: restored log file "000000010000000000000008" from archive
2020-10-01 18:03:21.574 PKT [71220] LOG: restored log file "000000010000000000000009" from archive
2020-10-01 18:03:22.286 PKT [71220] LOG: restored log file "00000001000000000000000A" from archive
2020-10-01 18:03:22.697 PKT [71220] LOG: recovery stopping before commit of transaction 508, time 2020-10-01 18:01:32.304189+05
2020-10-01 18:03:22.697 PKT [71220] LOG: pausing at the end of recovery
2020-10-01 18:03:22.697 PKT [71220] HINT: Execute pg_wal_replay_resume() to promote.

Connect to this cluster and see if we still have data in the foo table?

postgres=# select count(*) from foo;
count
---------
1000000
(1 row)

See when the recovery stopped, we still have the data!

Conclusion

PITR is a critical process to recover important data in case of a server crash which may result in an invalid/corrupt data directory leading to downtime. However, what can be prevented is the impact of a crash resulting in data loss. 

Keeping an up-to-date full backup with WAL files will lead to a simple and convenient restoration process. The time recovery time will depend on how recent the full backup was and how many WAL files were generated past it.

Tidak ada komentar:

Posting Komentar