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

Saat melakukan PITR, apakah mungkin untuk Menjeda/Melanjutkan di PostgreSQL ?

Ya, sangat mungkin dan ditangani dengan cerdas oleh PostgreSQL. Untuk mendemonstrasikan ini, pertama-tama saya harus mengikuti teknik standar Point in Time Recovery di PostgreSQL. Berbagai Buku/Artikel/Blog didemonstrasikan dengan sangat baik oleh penulis luar biasa, oleh karena itu saya tidak akan membahas secara rinci bagaimana melakukannya, namun, langsung menuju ke subjek yaitu, bagaimana menjeda saat memulihkan dengan teknik yang sama. Diperdebatkan, saya mengajukan ekspresi matematika dari PITR sebagai "PITR =(Cadangan Sistem File Terakhir (LFB) + Arsip WAL yang dihasilkan setelah LFB + WAL yang Tidak Diarsipkan di $PGDATA/pg_xlogs saat ini)". Untuk pemahaman yang lebih baik, saya telah memasukkan ini ke dalam grafik, karena itu lebih memperjelas pemikiran:(Maaf, blog ini agak panjang, tanpa sadar itu terjadi saat membahas detail konsep)

Langkah-langkah PITR, yang akan diikuti dengan sedikit perubahan yang akan segera saya bicarakan:

Langkah 1. Pulihkan cadangan tingkat Sistem File (FSB) terbaru ke lokasi tempat pemulihan direncanakan.
Langkah 2. Jika FSB adalah tar, maka untar, dan bersihkan direktori pg_xlog meninggalkan archive_status. Jika cadangan telah mengecualikan direktori ini, buat direktori pg_xlog kosong di FSB.
Langkah 3. Salin WAL yang tidak diarsipkan dari cluster yang mogok $PGDATA/pg_xlog ke $FSB/pg_xlog (Langkah 2)
Langkah 4. Hapus postmaster.pid dari direktori FSB.
Langkah 5. Buat file recovery.conf di direktori FSB.
Langkah 6. Mulai cluster (FSB).

Kita harus mengajukan pertanyaan, kapan menghentikan pemulihan diperlukan?. Mungkin, untuk mencegah beberapa restorasi basis atau pemulihan roll-forward tetapi periksa di antara atau kembalikan data atau minat tabel tertentu untuk melihat seberapa jauh itu telah pulih :). Ingat, jeda dalam pemulihan berarti, memungkinkan untuk terhubung saat memulihkan. Untuk menguraikan ini, saya telah mereproduksi situasi dalam bagan dari peningkatan baris tabel tertentu hingga menjadi kecelakaan.

Dari diagram di atas, baris tabel DEMO yang disetujui adalah 10.00.000 ketika cadangan tingkat sistem file($PGDATA) diambil dan 40.00.000 baris sebelum crash. Di VM lokal saya, saya telah membuat situasi berdasarkan TIME alih-alih tanggal.

Prasyaratan:
1. Pencadangan Tingkat Sistem File saat tabel DEMO memiliki 10.000 baris.
2. Sejak saat itu, Arsip WAL sebelum crash di mana tabel DEMO memiliki 40.000.000 baris.
3. Lokasi Arsip WAL:/opt/PostgreSQL/9.3/archives.
4. Direktori Data :/opt/PostgreSQL/9.3/data (PGDATA)
5. Lokasi Cadangan :/opt/PostgreSQL/9.3/backups

Perlu diingat, bekerja dengan pemulihan jeda memerlukan perubahan wajib pada cluster utama($PGDATA) "wal_level" disetel ke "hot_standby" dan pada cluster pemulihan (cadangan tingkat sistem file) "hot_standby" disetel ke "ON". Saya telah membuat perubahan ini pada klaster utama, memulai kembali klaster agar berlaku dan memulai pencadangan. Jika Anda tidak keberatan membuat catatan itu hanya demo, jadi arsip WAL saya mungkin bukan nomor raksasa karena jumlahnya sedikit. Saya juga telah mencantumkan arsip WAL di sini, yang dihasilkan dari waktu pencadangan hingga mogok.

-bash-4.1$ psql -c "select count(*), now() from demo;"
count | now
---------+-------------------------------
1000000 | 2014-04-04 15:06:04.036928-07
(1 row)

-bash-4.1$ pg_basebackup -D /opt/PostgreSQL/9.3/backup/data_pitr -- I have my $PGDATA, $PGUSER, $PGPORT set, so its a straight command in my case
NOTICE: pg_stop_backup complete, all required WAL segments have been archived

Status arsip WAL saat ini dan $PGDATA/pg_xlog

-bash-4.1$ ls -lrth /opt/PostgreSQL/9.3/archives
-rw------- 1 postgres postgres 16M Apr 4 16:01 00000001000000000000001C
-rw------- 1 postgres postgres 16M Apr 4 16:01 00000001000000000000001D
-rw------- 1 postgres postgres 289 Apr 4 16:06 00000001000000000000001E.000000C8.backup
-rw------- 1 postgres postgres 16M Apr 4 16:06 00000001000000000000001E

-bash-4.1$ ls -lrth /opt/PostgreSQL/9.3/data/pg_xlog | tail -4
-rw------- 1 postgres postgres 289 Apr 4 16:06 00000001000000000000001E.000000C8.backup
-rw------- 1 postgres postgres 16M Apr 4 16:06 00000001000000000000001E
-rw------- 1 postgres postgres 16M Apr 4 16:06 00000001000000000000001F
drwx------ 2 postgres postgres 4.0K Apr 4 16:13 archive_status

Baik sekarang, kami memiliki salinan cadangan, memungkinkan INSERT beberapa catatan dalam tiga bagian dengan mencatat waktu, sehingga akan membantu untuk menjeda pemulihan dan juga melihat WAL yang dihasilkan dari waktu FSB.

-bash-4.1$ psql -c "insert into demo values (generate_series(1,1000000));"
INSERT 0 1000000
-bash-4.1$ psql -c "select count(*),now() from demo;"
count | now
---------+-------------------------------
2000000 | 2014-04-04 16:06:34.941615-07
(1 row)
-bash-4.1$ psql -c "insert into demo values (generate_series(1,1000000));"
INSERT 0 1000000
-bash-4.1$ psql -c "select count(*),now() from demo;"
count | now
---------+-------------------------------
3000000 | 2014-04-04 16:10:31.136725-07
(1 row)
-bash-4.1$ psql -c "insert into demo values (generate_series(1,1000000));"
INSERT 0 1000000
-bash-4.1$ psql -c "select count(*),now() from demo;"
count | now
---------+-------------------------------
4000000 | 2014-04-04 16:13:00.136725-07
(1 row)

Periksa jumlah WAL yang diproduksi selama INSERT.

-bash-4.1$ ls -lrth /opt/PostgreSQL/9.3/archives
-rw------- 1 postgres postgres 289 Apr 4 16:06 00000001000000000000001E.000000C8.backup
-rw------- 1 postgres postgres 16M Apr 4 16:06 00000001000000000000001E
-rw------- 1 postgres postgres 16M Apr 4 16:06 00000001000000000000001F
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000020
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000021
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000022
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000023
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000024
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000025
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000026
-rw------- 1 postgres postgres 16M Apr 4 16:10 000000010000000000000027
-rw------- 1 postgres postgres 16M Apr 4 16:10 000000010000000000000028
-rw------- 1 postgres postgres 16M Apr 4 16:10 000000010000000000000029
-rw------- 1 postgres postgres 16M Apr 4 16:10 00000001000000000000002A
-rw------- 1 postgres postgres 16M Apr 4 16:13 00000001000000000000002B

Asumsikan pada titik ini terjadi kecelakaan dan Anda harus melakukan pemulihan menggunakan arsip FSB + WAL + WAL yang tidak diarsipkan (jika ada). Selama pemulihan, saya ingin berhenti tiga kali untuk melihat setiap pemulihan dari 20.000.000, 30.000.000 dan 40.00.000 baris tabel DEMO dengan menghubungkan ke database dalam mode READ-ONLY. Untuk setiap resume pemulihan, perlu restart cluster pemulihan dengan menabrak timeline baru di recovery.conf/recovery_target_time. Juga, di $FSB/postgresql.conf, kita harus mengatur hot_standby=on. Ini file recovery.conf saya:

-bash-4.1$ more recovery.conf
pause_at_recovery_target = true
#recovery_target_time = '2014-04-04 16:06:34' # For 2 lakh records
#recovery_target_time = '2014-04-04 16:10:31' # For 3 lakh records
#recovery_target_time = '2014-04-04 16:13:00' # For 4 lakh records
restore_command = 'cp /opt/PostgreSQL/9.3/archives/%f %p'

Mari kita mulai pemulihan untuk 20.000.000 catatan:

-bash-4.1$ /opt/PostgreSQL/9.3/bin/pg_ctl -D /opt/PostgreSQL/9.3/data_pitr/ start
server starting

Now in logs:

-bash-4.1$ more postgresql-2014-04-04_162524.log
2014-04-04 16:25:24 PDT-24187---[] LOG: starting point-in-time recovery to 2014-02-06 18:48:56-08
2014-04-04 16:25:24 PDT-24187---[] LOG: restored log file "00000001000000000000001E" from archive
2014-04-04 16:25:24 PDT-24187---[] LOG: redo starts at 0/1E0000C8
2014-04-04 16:25:24 PDT-24187---[] LOG: consistent recovery state reached at 0/1E000190
2014-04-04 16:25:24 PDT-24185---[] LOG: database system is ready to accept read only connections
2014-04-04 16:25:24 PDT-24187---[] LOG: restored log file "00000001000000000000001F" from archive
2014-04-04 16:25:24 PDT-24187---[] LOG: restored log file "000000010000000000000020" from archive
2014-04-04 16:25:25 PDT-24187---[] LOG: restored log file "000000010000000000000021" from archive
2014-04-04 16:25:25 PDT-24187---[] LOG: restored log file "000000010000000000000022" from archive
2014-04-04 16:25:25 PDT-24187---[] LOG: recovery stopping before commit of transaction 1833, time 2014-04-04 16:06:23.893487-07
2014-04-04 16:25:25 PDT-24187---[] LOG: recovery has paused
2014-04-04 16:25:25 PDT-24187---[] HINT: Execute pg_xlog_replay_resume() to continue

Keren, lihat di log itu telah berhenti dan PETUNJUK cerdas meminta untuk melanjutkan. Di sini, jika pemulihan memuaskan, Anda dapat melanjutkannya dengan memanggil "pilih pg_xlog_replay_resume();"(Anda dapat memeriksanya). Mari kita tidak melanjutkan sekarang, namun periksa jumlah baris yang dipulihkan dengan menghubungkan ke server.

-bash-4.1$ psql -c "select count(*),pg_is_in_recovery() from demo;"
count | pg_is_in_recovery
---------+-------------------
2000000 | t
(1 row)

Bagus, sudah sampai ke titik dan berhenti di tempat yang saya minta. Mari maju selangkah lebih maju untuk memulihkan 30.000.000 baris. Sekarang, tetapkan timeline berikutnya di recovery.conf/recovery_target_time dan mulai ulang cluster.

2014-04-04 16:28:40 PDT-24409---[] LOG:  restored log file "00000001000000000000002A" from archive
2014-04-04 16:28:40 PDT-24409---[] LOG: recovery stopping before commit of transaction 1836, time 2014-04-04 16:10:40.141175-07
2014-04-04 16:28:40 PDT-24409---[] LOG: recovery has paused
2014-04-04 16:28:40 PDT-24409---[] HINT: Execute pg_xlog_replay_resume() to continue.

-bash-4.1$ psql -c "select count(*),pg_is_in_recovery() from demo;"
count | pg_is_in_recovery
---------+-------------------
3000000 | t
(1 row)

Bagus…, mari kita lakukan upaya terakhir untuk menjeda pada 40.000.000 baris.

2014-04-04 20:09:07 PDT-4723---[] LOG:  restored log file "00000001000000000000002B" from archive
cp: cannot stat `/opt/PostgreSQL/9.3/archives/00000001000000000000002C': No such file or directory
2014-04-04 20:09:07 PDT-4723---[] LOG: redo done at 0/2B0059A0
2014-04-04 20:09:07 PDT-4723---[] LOG: last completed transaction was at log time 2014-04-04 16:11:12.264512-07
2014-04-04 20:09:07 PDT-4723---[] LOG: restored log file "00000001000000000000002B" from archive
2014-04-04 20:09:07 PDT-4723---[] LOG: restored log file "00000002.history" from archive
2014-04-04 20:09:07 PDT-4723---[] LOG: restored log file "00000003.history" from archive
2014-04-04 20:09:07 PDT-4723---[] LOG: restored log file "00000004.history" from archive
cp: cannot stat `/opt/PostgreSQL/9.3/archives/00000005.history': No such file or directory
2014-04-04 20:09:07 PDT-4723---[] LOG: selected new timeline ID: 5
cp: cannot stat `/opt/PostgreSQL/9.3/archives/00000001.history': No such file or directory
2014-04-04 20:09:07 PDT-4723---[] LOG: archive recovery complete
2014-04-04 20:09:08 PDT-4721---[] LOG: database system is ready to accept connections
2014-04-04 20:09:08 PDT-4764---[] LOG: autovacuum launcher started

-bash-4.1$ psql -c "select count(*),pg_is_in_recovery() from demo;"
count | pg_is_in_recovery
---------+-------------------
4000000 | f
(1 row)

Ups, apa yang terjadi, mengapa tidak berhenti dan apa keluhannya?. Perlu diingat, jika tidak ada arsip WAL pada saat recovery_target_time maka tidak akan berhenti dan berharap karena telah sampai pada titik terakhir dan membuka database untuk READ/WRITE. Dalam log, tanpa banyak usaha, ia mencari file “00000001000000000000002C” yang tidak tersedia, karena pada saat itu cluster sedang crash. Beberapa mungkin tidak mengakui perilaku ini tetapi faktanya dan masuk akal ketika tidak ada arsip WAL yang ada maka tidak ada alasan untuk menjeda pemulihan. Jika sama sekali diperlukan untuk menjeda bahkan setelah tidak ada arsip WAL, maka gunakan standby_mode='on' (HOT_STANDBY), dalam metode ini tidak akan keluar dari pemulihan tetapi menunggu Arsip WAL.

Semoga bermanfaat.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana menjaga data tidak mengurutkan?

  2. Postgres Kiri Gabung dengan kondisi dimana

  3. Bagaimana cara mengubah pemformatan untuk nilai yang saya kembalikan dalam fungsi ini?

  4. Menambahkan kolom sebagai kunci asing memberikan kolom KESALAHAN yang direferensikan dalam batasan kunci asing tidak ada

  5. STRING_AGG() Fungsi di PostgreSQL