2016年8月31日水曜日

PostgreSQLのバックアップとリストア

こんにちは。

データベースにとってバックアップは最後の命綱です。バックアップとリストアを完全に理解することは安全なデータベース運用には欠かせません。今回は PostgreSQL9.3 を用いて、バックアップとリストアの全機能を簡単に紹介します。

■ データベースのバックアップとリストア

PostgreSQL では以下の方法が利用できます。

  • ファイルのバックアップ (ただし、オフラインバックアップのみ)
  • ファイルシステムのスナップショット (オンラインバックアップ可能)
  • pg_dump / pg_dumpall コマンドによるバックアップ (オンラインバックアップ可能)
  • アーカイブログによるバックアップ (非同期にバックアップ & 任意時点へのリカバリ可能)

レプリケーションもバックアップの一種と考えることも可能です。しかし、レプリケーションの場合

  • 操作ミス、攻撃などによるデータ破壊が発生した場合に対応できない

という欠点があります。ディスクのミラーリングなどの冗長性確保をデータのバックアップととらえないことと同様に、ここではレプリケーションはバックアップには入れないことにします。ここでは説明しませんが、レプリケーションを行いながらアーカイブログを利用したバックアップを行うことも簡単です。

■ バックアップの種類と特徴

PostgreSQL データベースをバックアップに利用できる方法を順番に紹介します。

■■ファイルのバックアップ

♦ 利点

  • バックアップ / リストアが高速

♦ 欠点

  • オンラインでのバックアップ / リストアができない
  • 一部のテーブル / データベースのバックアップ / リストアができない
  • 同じバージョンの PostgreSQL でなければならない

initdb コマンドで指定する PostgreSQL のデータクラスタのディレクトリを丸ごとバックアップする方法です。この方法はファイルをバックアップするので高速です。リストアもファイルのリストアなので高速です。データベースは停止していなければなりません。ファイルバックアップを PostgreSQL 動作中に行うとデータベースにファイルに不整合が発生し、リストアしても使えないデータを取得することになります。

コマンド例

tar -jcvf backup.tar.bz2 /usr/local/pgsql/data

■■ファイルシステムのスナップショット

♦ 利点

  • バックアップ / リストアが高速
  • バックアップはオンラインで可能(スナップショット取得開始時点での整合性を維持できる場合)

♦ 欠点

  • オンラインでのリストアができない
  • 一部のテーブル / データベースのバックアップ/リストアができない
  • OS のファイルシステムに依存する (いつでも使えない)
  • リストアする場合にデータベースが強制終了した後の状態になる (エラーが発生するだけで、実際に問題となることはない)
  • 同じバージョンの PostgreSQL でなければならない

ファイルシステムがスナップショットの取得時に整合性を保てる場合、スナップショットをバックアップに利用できます。Btrfs、XFS などのファイルシステムは整合性を保ったスナップショットの取得が可能です。スナップショットはファイルのバックアップ / リストアよりさらに高速です。

コマンド例 (Btrfs)

btrfs subvolume snapshot /usr/local/pgsql/data /usr/local/pgsql/data/snapshot1

■■pg_dump/pg_dumpallコマンド

♦ 利点

  • オンラインでのバックアップ / リストアが可能
  • テーブル / データベース単位でのバックアップ / リストアが可能
  • リモートホストのバックアップ / リストアが可能
  • PostgreSQL バージョンアップ時のバックアップ / リストアとして利用可能

♦ 欠点

  • バックアップ / リストアが低速

PostgreSQL の pg_dump コマンドを利用するとオンラインでのバックアップ / リストア、テーブル、データベース毎のバックアップ / リストアが可能になります。データベース全体でなく、一部をバックアップ / リストアできることが利点です。データベースによってはオンラインバックアップで整合性のあるバックアップを取得できなかったり、ロックが発生する物もあります。PostgreSQL の場合、ロック無しに整合性のあるバックアップを取得できます。

PostgreSQL のバージョンアップ (例えば、9.3 から 9.4 へのバージョンアップ) にはデータのバックアップ / リストアを行うか、pg_upgrade コマンドによるデータベースファイルのアップグレードが必要です。ファイル / スナップショットによるバックアップはバージョンアップの為のバックアップ & リストアには利用できません。pg_dumpall とリストア、または pg_upgrade によるアップグレードが必要です。

コマンド例

# バックアップ
pg_dump -p 5433 -h 10.10.10.10 dbname > backup_file
 
# リストア
psql -p 5433 -h 10.10.10.10 dbname < backup_file
 

■■アーカイブログによるバックアップ

♦ 利点

  • オンラインでバックアップ / リストアが可能
  • バックアップが高速
  • 常に新しい差分バックアップが取得可能
  • 任意時点へのリカバリ (PITR) が可能

♦ 欠点

  • バックアップ / リストアの為のセットアップが必要
  • ベースバックアップの取得が必要
  • リストアが低速 (特にベースバックアップが古い場合)
  • バックアップデータが大きくなる
  • 同じバージョンの PostgreSQL でなければならない

アーカイブログによるバックアップが最も手順が複雑ですが、常に差分バックアップが取得可能であること、任意時点へのリカバリ (PITR - Point In Time Recovery) が可能であることは大きなメリットです。アーカイブログは普通のファイルなので、NFS などを利用してリモートのシステムに保存することも可能です。リモートの PostgreSQL をコールドスタンバイとした冗長構成を取ることも可能です。

■ アーカイブログによるバックアップの仕組み

PostgreSQL はデータベースのデータファイルに直接データを書き込みません。WAL (Write Ahead Log) と呼ばれるバイナリのトランザクションログにデータ操作を記録します。その後、実際のデータファイルに更新を反映していきます。WAL により、電源断などの障害が発生した場合のリカバリと、ディスクヘッドの動きを最小限にしてデータベースの動作を高速化しています。

つまり、アーカイブログにはデータベースへの操作が順番に全て記録されています。元となるデータベースのバックアップ (ベースバックアップ) とその後のアーカイブログがあれば、直近の状態にまでリストアできます。リストアする時にはアーカイブログを利用しデータベース操作を 「再生」 するので、通常のリストアより時間がかかります。 (例 : 同じレコードを何度も更新している場合、全ての更新が 「再生」 される) つまり、障害時のダウンタイムを少くするには、頻繁にベースバックアップを取得しなければなりません。

■■ ベースバックアップの取得

ベースバックアップの取得にはオフラインで取得する方法(データファイルを利用する方法)とオンラインで取得する方法(専用コマンドを利用する方法)の 2 種類があります。オンラインで利用できる pg_basebackup コマンドが最も簡単にベースバックアップを取得できます。通常は pg_basebackup コマンドを利用すると良いでしょう。

pg_basebackup の利用例

# ローカルデータベースの tar.bz2 形式のベースバックアップを取得
pg_basebackup -D - -Ft | bzip2 > backup.tar.bz2
 
# リモートホスト(remote)のデータベースクラスタをローカルに作成
pg_basebackup -h remote -D /usr/local/pgsql/data

pg_basebackup コマンドはレプリケーションアクセスが必要です。pg_hba.conf で pg_basebackup コマンドを実行するユーザーに replication の許可をします。

pg_hba.conf の例

# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     username                                trust
host    replication     username        127.0.0.1/32            trust
host    replication     username        ::1/128                 trust

postgresql.conf の max_wal_sender 設定のデフォルトは 0 です。最低でも 1 以上でないと pg_basebackup コマンドは実行できないので修正します。

postgresql.conf の例

max_wal_sender = 1

■■ WALアーカイブの有効化

デフォルトの場合、アーカイブログは 16MB 毎に作成され pg_xlog ディレクトリに保存されます。必要がなくなったアーカイブログは自動的に削除されます。アーカイブログによるバックアップを行う場合、アーカイブログファイルを消す前に他の場所にコピーします。これは postgresql.conf にアーカイブログに必要な設定を行い、ファイルをコピーするコマンドを書きます。

♦ WALアーカイブの有効化の手順

  1. wal_level 設定を archive (または hot_standby) に設定する
  2. archive_mode 設定を on に設定する
  3. archive_command 設定にコピーコマンドを設定する

archive_command の設定例

archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'  # Unix
archive_command = 'copy "%p" "C:¥¥server¥¥archivedir¥¥%f"'  # Windows

これでアーカイブログが保存できます。

■■ アーカイブログを利用したリカバリ

♦ ここでは同じサーバーにリカバリする手順を紹介します。

  1. サーバーを停止する。
  2. 少なくともデータクラスタ内の pg_xlog ディレクトリをコピーする。(可能であればデータクラスタのファイル全てを保存する)
  3. データクラスタ内の全てのファイルを削除する。
  4. pg_basebackup で作成したベースバックアップをリストアする。
  5. もし pg_xlog ディレクトリに内にファイルがある場合は全て削除する。(ファイル、スナップショットのベースバックアップの場合は pg_xlog 内にファイルが残っている)
  6. ステップ 2 での WAL ファイルがある場合、pg_xlog ディレクトリにコピーする
  7. リカバリーコマンドを recovery.conf に記述する。pg_hba.conf ファイルでリカバリ中にユーザーが接続しないように設定する。
  8. サーバーを起動する。リカバリーモードとなり、リカバリが開始される。リカバリーが完了すると recovery.conf は recovery.done に名前が変更される。
  9. データが意図通りにリストアされているか確認する。問題ない場合は pg_hba.conf を修正し、ユーザーのアクセスを許可し、サーバーを再起動する。

■■recovery.conf の設定

recovery.conf ファイルには次の 3 つのコマンド設定が行えます。

restore_command 設定の例

restore_command = 'cp /mnt/server/archivedir/%f "%p"' # UNIX
restore_command = 'copy "C:¥¥server¥¥archivedir¥¥%f" "%p"'  # Windows

restore_command には postgresql.conf の archive_command で指定したディレクトリを指定します。この設定はリカバリに必須です。

archive_cleanup_command 設定の例

archive_cleanup_command = 'pg_archivecleanup /mnt/server/archivedir %r'

pg_archivecleanup コマンドは不要になったアーカイブログを削除します。一 つのアーカイブログから複数のサーバーをリカバリする場合やアーカイブログを保存したい場合はこの設定は必要ありません。

recovery_end_command 設定はリカバリが完了した場合に一度だけ実行されるコマンドを記述します。

リカバリーターゲット設定は以下の 3 つの設定が利用できます。

  • recovery_target_name (文字列):pg_create_restore_point 関数で指定された時点を指定する。
  • recovery_target_time (timestamp) :時刻を指定する。
  • recovery_target_xid (文字列) :トランザクション ID を指定する。

これら 3 つのうちの 1 つを指定します。また、リカバリーターゲットの取り扱いに次の 3 つのオプションが指定できます。

  • recovery_target_inclusive (論理値) : リカバリーターゲットを含む場合は true、リカバリーターゲットの直前までリストアする場合は false を指定する。
  • recovery_target_timeline (文字列) : タイムラインを指定する。詳しくは PostgreSQL 9.3 マニュアルの 24.3.5. Timelines を参照してください。
  • pause_at_recovery_target (論理値) : リカバリーターゲットに達した場合にリカバリーを停止する。デフォルトは true。

■■実際の実行例

次の実行例は以下の操作を行っています。

  1. 新規データベースを作成 (initdb)
    [pguser@dev tmp]$ initdb pgdata
    
  2. アーカイブログに必要な設定ファイルを作成 (postgresql.conf, pg_hba.conf)
    [pguser@dev tmp]$ cp postgresql.conf pg_hba.conf pgdata
    
  3. データベースを開始 (pg_ctl start)
    [pguser@dev tmp]$ pg_ctl -D pgdata start
    
  4. ベースバックアップを作成 (pg_basebackup)
    [pguser@dev tmp]$ pg_basebackup -D - -Ft | bzip2 > backup.tar.bz2
    
  5. データベースを 3 つ作成 (createdb)
    [pguser@dev tmp]$ createdb db1
    [pguser@dev tmp]$ createdb db2
    [pguser@dev tmp]$ createdb db3
    
  6. リカバリターゲット時間となる時間を取得 (select now())
    [pguser@dev tmp]$ psql  -c  'select now();' db1
    
  7. 誤って db2 をドロップ (dropdb)
    [pguser@dev tmp]$ drop db2
    
  8. データベースを停止 (pg_ctl stop)
    [pguser@dev tmp]$ pg_ctl -D pgdata stop
    
  9. データベースクラスタを削除 (rm -rf pgdata/*)
    [pguser@dev tmp]$ rm -rf pgdata/*
    
  10. ベースバックアップをリカバリ (tar jxvf ../backup.tar.bz2)
    [pguser@dev tmp]$ (cd pgdata/; tar jxvf ../backup.tar.bz2)
    
  11. リカバリ設定をコピー (recovery.conf)
    [pguser@dev tmp]$ cp recovery.conf pgdata/
    
  12. データベースを開始&リカバリ開始 (pg_ctl -D pgdata start)
    [pguser@dev tmp]$ pg_ctl -D pgdata start
    
  13. リカバリ後に誤ってドロップした db2 が存在することを確認 (psql -l)
    [pguser@dev tmp]$ psql -l
    
pguser@dev tmp]$ initdb pgdata
The files belonging to this database system will be owned by user "pguser".
This user must also own the server process.

The database cluster will be initialized with locale "ja_JP.utf8".
The default database encoding has accordingly been set to "UTF8".
initdb: could not find suitable text search configuration for locale "ja_JP.utf8"
The default text search configuration will be set to "simple".

Data page checksums are disabled.

creating directory pgdata ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
creating configuration files ... ok
creating template1 database in pgdata/base/1 ... ok
initializing pg_authid ... ok
initializing dependencies ... ok
creating system views ... ok
loading system objects' descriptions ... ok
creating collations ... ok
creating conversions ... ok
creating dictionaries ... ok
setting privileges on built-in objects ... ok
creating information schema ... ok
loading PL/pgSQL server-side language ... ok
vacuuming database template1 ... ok
copying template1 to template0 ... ok
copying template1 to postgres ... ok
syncing data to disk ... ok

WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

    postgres -D pgdata
or
    pg_ctl -D pgdata -l logfile start


[pguser@dev tmp] diff -u pgdata/postgresql.conf postgresql.conf
--- pgdata/postgresql.conf 2014-11-28 17:52:54.020012187 +0900
+++ postgresql.conf 2014-11-28 16:36:54.078142219 +0900
@@ -160,7 +160,7 @@
 
 # - Settings -
 
-#wal_level = minimal   # minimal, archive, or hot_standby
+wal_level = archive   # minimal, archive, or hot_standby
      # (change requires restart)
 #fsync = on    # turns forced synchronization on or off
 #synchronous_commit = on  # synchronization level;
@@ -189,9 +189,9 @@
 
 # - Archiving -
 
-#archive_mode = off  # allows archiving to be done
+archive_mode = on  # allows archiving to be done
     # (change requires restart)
-#archive_command = ''  # command to use to archive a logfile segment
+archive_command = 'test ! -f /tmp/archivedir/%f && cp %p /tmp/archivedir/%f'  # command to use to archive a logfile segment
     # placeholders: %p = path of file to archive
     #               %f = file name only
     # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
@@ -207,7 +207,7 @@
 
 # Set these on the master and on any standby that will send replication data.
 
-#max_wal_senders = 0  # max number of walsender processes
+max_wal_senders = 2  # max number of walsender processes
     # (change requires restart)
 #wal_keep_segments = 0  # in logfile segments, 16MB each; 0 disables
 #wal_sender_timeout = 60s # in milliseconds; 0 disables


[pguser@dev tmp]$ diff -u pgdata/pg_hba.conf pg_hba.conf 
--- pgdata/pg_hba.conf 2014-11-28 17:52:54.020012187 +0900
+++ pg_hba.conf 2014-11-28 16:37:08.969043881 +0900
@@ -88,6 +88,6 @@
 host    all             all             ::1/128                 trust
 # Allow replication connections from localhost, by a user with the
 # replication privilege.
-#local   replication     pguser                                trust
-#host    replication     pguser        127.0.0.1/32            trust
-#host    replication     pguser        ::1/128                 trust
+local   replication     pguser                                trust
+host    replication     pguser        127.0.0.1/32            trust
+host    replication     pguser        ::1/128                 trust


[pguser@dev tmp]$ cp postgresql.conf pg_hba.conf pgdata
cp: `pgdata/postgresql.conf' を上書きしますか? yes
cp: `pgdata/pg_hba.conf' を上書きしますか? yes

[pguser@dev tmp]$ pg_ctl -D pgdata start
server starting
[pguser@dev tmp]$ LOG:  database system was shut down at 2014-11-28 17:52:54 JST
LOG:  database system is ready to accept connections
LOG:  autovacuum launcher started

[pguser@dev tmp]$ pg_basebackup -D - -Ft | bzip2 > backup.tar.bz2
NOTICE:  pg_stop_backup complete, all required WAL segments have been archived
[pguser@dev tmp]$ createdb db1
[pguser@dev tmp]$ createdb db2
[pguser@dev tmp]$ createdb db3
[pguser@dev tmp]$ psql -l
Timing is on.
Null display is "?".
Line style is unicode.
Border style is 2.
You are connected to database "postgres" as user "pguser" via socket in "/tmp" at port "5432".
                                List of databases
┌───────────┬─────────┬──────────┬────────────┬────────────┬─────────────────────┐
│   Name    │  Owner  │ Encoding │  Collate   │   Ctype    │  Access privileges  │
├───────────┼─────────┼──────────┼────────────┼────────────┼─────────────────────┤
│ db1       │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │                     │
│ db2       │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │                     │
│ db3       │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │                     │
│ postgres  │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │                     │
│ template0 │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │ =c/pguser         ?│
│           │         │          │            │            │ pguser=CTc/pguser │
│ template1 │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │ =c/pguser         ?│
│           │         │          │            │            │ pguser=CTc/pguser │
└───────────┴─────────┴──────────┴────────────┴────────────┴─────────────────────┘
(6 rows)

[pguser@dev tmp]$ psql  -c  'select now();' db1
              now              
-------------------------------
 2014-11-28 17:54:26.212748+09
(1 row)

[pguser@dev tmp]$ drop db2
[pguser@dev tmp]$ psql -l
Timing is on.
Null display is "?".
Line style is unicode.
Border style is 2.
You are connected to database "postgres" as user "pguser" via socket in "/tmp" at port "5432".
                                List of databases
┌───────────┬─────────┬──────────┬────────────┬────────────┬─────────────────────┐
│   Name    │  Owner  │ Encoding │  Collate   │   Ctype    │  Access privileges  │
├───────────┼─────────┼──────────┼────────────┼────────────┼─────────────────────┤
│ db1       │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │                     │
│ db3       │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │                     │
│ postgres  │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │                     │
│ template0 │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │ =c/pguser         ?│
│           │         │          │            │            │ pguser=CTc/pguser │
│ template1 │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │ =c/pguser         ?│
│           │         │          │            │            │ pguser=CTc/pguser │
└───────────┴─────────┴──────────┴────────────┴────────────┴─────────────────────┘
(5 rows)

[pguser@dev tmp]$ pg_ctl -D pgdata stop
waiting for server to shut down....LOG:  received smart shutdown request
LOG:  autovacuum launcher shutting down
LOG:  shutting down
LOG:  database system is shut down
 done
server stopped

[pguser@dev tmp]$ rm -rf pgdata/*
[pguser@dev tmp]$ (cd pgdata/; tar jxvf ../backup.tar.bz2)
backup_label
global/
global/pg_filenode.map
global/12692
global/12694
global/12695
global/12825
global/12827
global/12829
global/12830
global/12831
global/12833
global/12834
global/12835
global/12837
global/12838
global/12840
global/12841
global/12842
global/12844
global/12845
global/12846
global/12848
global/12850
global/12851
global/12896
global/12898
global/12692_vm
global/12692_fsm
global/12831_vm
global/12831_fsm
global/12835_vm
global/12835_fsm
global/12842_vm
global/12842_fsm
global/12846_vm
global/12846_fsm
global/12945
global/12947
global/12948
pg_xlog/
pg_clog/
pg_clog/0000
pg_notify/
pg_notify/0000
pg_serial/
pg_snapshots/
pg_subtrans/
pg_subtrans/0000
pg_twophase/
pg_multixact/
pg_multixact/members/
pg_multixact/members/0000
pg_multixact/offsets/
pg_multixact/offsets/0000
base/
base/1/
base/1/pg_filenode.map
base/1/PG_VERSION
base/1/12682
base/1/12684
base/1/12686
base/1/12687
base/1/12688
base/1/12690
base/1/12691
base/1/12696
base/1/12698
base/1/12699
base/1/12700
base/1/12702
base/1/12703
base/1/12704
base/1/12700_fsm
base/1/12706
base/1/12708
base/1/12709
base/1/12710
base/1/12711
base/1/12713
base/1/12714
base/1/12715
base/1/12717
base/1/12719
base/1/12720
base/1/12721
base/1/12722
base/1/12724
base/1/12726
base/1/12727
base/1/12728
base/1/12729
base/1/12730
base/1/12731
base/1/12733
base/1/12734
base/1/12735
base/1/12737
base/1/12738
base/1/12739
base/1/12741
base/1/12742
base/1/12743
base/1/12745
base/1/12746
base/1/12747
base/1/12749
base/1/12750
base/1/12751
base/1/12753
base/1/12754
base/1/12755
base/1/12757
base/1/12758
base/1/12759
base/1/12760
base/1/12762
base/1/12763
base/1/12764
base/1/12766
base/1/12767
base/1/12768
base/1/12770
base/1/12771
base/1/12773
base/1/12774
base/1/12776
base/1/12778
base/1/12779
base/1/12780
base/1/12781
base/1/12783
base/1/12785
base/1/12786
base/1/12787
base/1/12788
base/1/12789
base/1/12791
base/1/12792
base/1/12793
base/1/12795
base/1/12797
base/1/12798
base/1/12799
base/1/12801
base/1/12802
base/1/12803
base/1/12805
base/1/12806
base/1/12807
base/1/12808
base/1/12810
base/1/12811
base/1/12812
base/1/12814
base/1/12815
base/1/12816
base/1/12817
base/1/12819
base/1/12820
base/1/12852
base/1/12854
base/1/12855
base/1/12856
base/1/12858
base/1/12859
base/1/12861
base/1/12862
base/1/12863
base/1/12865
base/1/12866
base/1/12867
base/1/12869
base/1/12870
base/1/12871
base/1/12873
base/1/12874
base/1/12875
base/1/12877
base/1/12878
base/1/12879
base/1/12881
base/1/12882
base/1/12883
base/1/12885
base/1/12886
base/1/12888
base/1/12889
base/1/12890
base/1/12892
base/1/12894
base/1/12895
base/1/12899
base/1/12901
base/1/12902
base/1/12903
base/1/12905
base/1/12906
base/1/12908
base/1/12909
base/1/12911
base/1/12913
base/1/12914
base/1/12916
base/1/12918
base/1/12919
base/1/12921
base/1/12923
base/1/12924
base/1/12926
base/1/12928
base/1/12929
base/1/12931
base/1/12933
base/1/12934
base/1/12936
base/1/12938
base/1/12939
base/1/12941
base/1/12943
base/1/12682_vm
base/1/12682_fsm
base/1/12684_vm
base/1/12684_fsm
base/1/12688_vm
base/1/12688_fsm
base/1/12700_vm
base/1/12704_vm
base/1/12704_fsm
base/1/12711_vm
base/1/12711_fsm
base/1/12722_vm
base/1/12722_fsm
base/1/12735_vm
base/1/12735_fsm
base/1/12739_vm
base/1/12739_fsm
base/1/12743_vm
base/1/12743_fsm
base/1/12747_vm
base/1/12747_fsm
base/1/12751_vm
base/1/12751_fsm
base/1/12755_vm
base/1/12755_fsm
base/1/12760_vm
base/1/12760_fsm
base/1/12764_vm
base/1/12764_fsm
base/1/12774_vm
base/1/12774_fsm
base/1/12776_vm
base/1/12776_fsm
base/1/12793_vm
base/1/12793_fsm
base/1/12799_vm
base/1/12799_fsm
base/1/12808_vm
base/1/12808_fsm
base/1/12812_vm
base/1/12812_fsm
base/1/12817_vm
base/1/12817_fsm
base/1/12852_vm
base/1/12852_fsm
base/1/12856_vm
base/1/12856_fsm
base/1/12859_vm
base/1/12859_fsm
base/1/12863_vm
base/1/12863_fsm
base/1/12867_vm
base/1/12867_fsm
base/1/12871_vm
base/1/12871_fsm
base/1/12903_vm
base/1/12903_fsm
base/1/12914_vm
base/1/12914_fsm
base/1/12919_vm
base/1/12919_fsm
base/1/12924_vm
base/1/12924_fsm
base/1/12934_vm
base/1/12934_fsm
base/1/12771_vm
base/1/12771_fsm
base/1/12909_vm
base/1/12909_fsm
base/1/12899_vm
base/1/12899_fsm
base/1/12929_vm
base/1/12929_fsm
base/12944/
base/12944/pg_filenode.map
base/12944/PG_VERSION
base/12944/12682
base/12944/12684
base/12944/12686
base/12944/12687
base/12944/12688
base/12944/12690
base/12944/12691
base/12944/12696
base/12944/12698
base/12944/12699
base/12944/12700
base/12944/12702
base/12944/12703
base/12944/12704
base/12944/12700_fsm
base/12944/12706
base/12944/12708
base/12944/12709
base/12944/12710
base/12944/12711
base/12944/12713
base/12944/12714
base/12944/12715
base/12944/12717
base/12944/12719
base/12944/12720
base/12944/12721
base/12944/12722
base/12944/12724
base/12944/12726
base/12944/12727
base/12944/12728
base/12944/12729
base/12944/12730
base/12944/12731
base/12944/12733
base/12944/12734
base/12944/12735
base/12944/12737
base/12944/12738
base/12944/12739
base/12944/12741
base/12944/12742
base/12944/12743
base/12944/12745
base/12944/12746
base/12944/12747
base/12944/12749
base/12944/12750
base/12944/12751
base/12944/12753
base/12944/12754
base/12944/12755
base/12944/12757
base/12944/12758
base/12944/12759
base/12944/12760
base/12944/12762
base/12944/12763
base/12944/12764
base/12944/12766
base/12944/12767
base/12944/12768
base/12944/12770
base/12944/12771
base/12944/12773
base/12944/12774
base/12944/12776
base/12944/12778
base/12944/12779
base/12944/12780
base/12944/12781
base/12944/12783
base/12944/12785
base/12944/12786
base/12944/12787
base/12944/12788
base/12944/12789
base/12944/12791
base/12944/12792
base/12944/12793
base/12944/12795
base/12944/12797
base/12944/12798
base/12944/12799
base/12944/12801
base/12944/12802
base/12944/12803
base/12944/12805
base/12944/12806
base/12944/12807
base/12944/12808
base/12944/12810
base/12944/12811
base/12944/12812
base/12944/12814
base/12944/12815
base/12944/12816
base/12944/12817
base/12944/12819
base/12944/12820
base/12944/12852
base/12944/12854
base/12944/12855
base/12944/12856
base/12944/12858
base/12944/12859
base/12944/12861
base/12944/12862
base/12944/12863
base/12944/12865
base/12944/12866
base/12944/12867
base/12944/12869
base/12944/12870
base/12944/12871
base/12944/12873
base/12944/12874
base/12944/12875
base/12944/12877
base/12944/12878
base/12944/12879
base/12944/12881
base/12944/12882
base/12944/12883
base/12944/12885
base/12944/12886
base/12944/12888
base/12944/12889
base/12944/12890
base/12944/12892
base/12944/12894
base/12944/12895
base/12944/12899
base/12944/12901
base/12944/12902
base/12944/12903
base/12944/12905
base/12944/12906
base/12944/12908
base/12944/12909
base/12944/12911
base/12944/12913
base/12944/12914
base/12944/12916
base/12944/12918
base/12944/12919
base/12944/12921
base/12944/12923
base/12944/12924
base/12944/12926
base/12944/12928
base/12944/12929
base/12944/12931
base/12944/12933
base/12944/12934
base/12944/12936
base/12944/12938
base/12944/12939
base/12944/12941
base/12944/12943
base/12944/12682_vm
base/12944/12682_fsm
base/12944/12684_vm
base/12944/12684_fsm
base/12944/12688_vm
base/12944/12688_fsm
base/12944/12700_vm
base/12944/12704_vm
base/12944/12704_fsm
base/12944/12711_vm
base/12944/12711_fsm
base/12944/12722_vm
base/12944/12722_fsm
base/12944/12735_vm
base/12944/12735_fsm
base/12944/12739_vm
base/12944/12739_fsm
base/12944/12743_vm
base/12944/12743_fsm
base/12944/12747_vm
base/12944/12747_fsm
base/12944/12751_vm
base/12944/12751_fsm
base/12944/12755_vm
base/12944/12755_fsm
base/12944/12760_vm
base/12944/12760_fsm
base/12944/12764_vm
base/12944/12764_fsm
base/12944/12774_vm
base/12944/12774_fsm
base/12944/12776_vm
base/12944/12776_fsm
base/12944/12793_vm
base/12944/12793_fsm
base/12944/12799_vm
base/12944/12799_fsm
base/12944/12808_vm
base/12944/12808_fsm
base/12944/12812_vm
base/12944/12812_fsm
base/12944/12817_vm
base/12944/12817_fsm
base/12944/12852_vm
base/12944/12852_fsm
base/12944/12856_vm
base/12944/12856_fsm
base/12944/12859_vm
base/12944/12859_fsm
base/12944/12863_vm
base/12944/12863_fsm
base/12944/12867_vm
base/12944/12867_fsm
base/12944/12871_vm
base/12944/12871_fsm
base/12944/12903_vm
base/12944/12903_fsm
base/12944/12914_vm
base/12944/12914_fsm
base/12944/12919_vm
base/12944/12919_fsm
base/12944/12924_vm
base/12944/12924_fsm
base/12944/12934_vm
base/12944/12934_fsm
base/12944/12771_vm
base/12944/12771_fsm
base/12944/12909_vm
base/12944/12909_fsm
base/12944/12899_vm
base/12944/12899_fsm
base/12944/12929_vm
base/12944/12929_fsm
base/12949/
base/12949/pg_filenode.map
base/12949/PG_VERSION
base/12949/12682
base/12949/12684
base/12949/12686
base/12949/12687
base/12949/12688
base/12949/12690
base/12949/12691
base/12949/12696
base/12949/12698
base/12949/12699
base/12949/12700
base/12949/12702
base/12949/12703
base/12949/12704
base/12949/12700_fsm
base/12949/12706
base/12949/12708
base/12949/12709
base/12949/12710
base/12949/12711
base/12949/12713
base/12949/12714
base/12949/12715
base/12949/12717
base/12949/12719
base/12949/12720
base/12949/12721
base/12949/12722
base/12949/12724
base/12949/12726
base/12949/12727
base/12949/12728
base/12949/12729
base/12949/12730
base/12949/12731
base/12949/12733
base/12949/12734
base/12949/12735
base/12949/12737
base/12949/12738
base/12949/12739
base/12949/12741
base/12949/12742
base/12949/12743
base/12949/12745
base/12949/12746
base/12949/12747
base/12949/12749
base/12949/12750
base/12949/12751
base/12949/12753
base/12949/12754
base/12949/12755
base/12949/12757
base/12949/12758
base/12949/12759
base/12949/12760
base/12949/12762
base/12949/12763
base/12949/12764
base/12949/12766
base/12949/12767
base/12949/12768
base/12949/12770
base/12949/12771
base/12949/12773
base/12949/12774
base/12949/12776
base/12949/12778
base/12949/12779
base/12949/12780
base/12949/12781
base/12949/12783
base/12949/12785
base/12949/12786
base/12949/12787
base/12949/12788
base/12949/12789
base/12949/12791
base/12949/12792
base/12949/12793
base/12949/12795
base/12949/12797
base/12949/12798
base/12949/12799
base/12949/12801
base/12949/12802
base/12949/12803
base/12949/12805
base/12949/12806
base/12949/12807
base/12949/12808
base/12949/12810
base/12949/12811
base/12949/12812
base/12949/12814
base/12949/12815
base/12949/12816
base/12949/12817
base/12949/12819
base/12949/12820
base/12949/12852
base/12949/12854
base/12949/12855
base/12949/12856
base/12949/12858
base/12949/12859
base/12949/12861
base/12949/12862
base/12949/12863
base/12949/12865
base/12949/12866
base/12949/12867
base/12949/12869
base/12949/12870
base/12949/12871
base/12949/12873
base/12949/12874
base/12949/12875
base/12949/12877
base/12949/12878
base/12949/12879
base/12949/12881
base/12949/12882
base/12949/12883
base/12949/12885
base/12949/12886
base/12949/12888
base/12949/12889
base/12949/12890
base/12949/12892
base/12949/12894
base/12949/12895
base/12949/12899
base/12949/12901
base/12949/12902
base/12949/12903
base/12949/12905
base/12949/12906
base/12949/12908
base/12949/12909
base/12949/12911
base/12949/12913
base/12949/12914
base/12949/12916
base/12949/12918
base/12949/12919
base/12949/12921
base/12949/12923
base/12949/12924
base/12949/12926
base/12949/12928
base/12949/12929
base/12949/12931
base/12949/12933
base/12949/12934
base/12949/12936
base/12949/12938
base/12949/12939
base/12949/12941
base/12949/12943
base/12949/12682_vm
base/12949/12682_fsm
base/12949/12684_vm
base/12949/12684_fsm
base/12949/12688_vm
base/12949/12688_fsm
base/12949/12700_vm
base/12949/12704_vm
base/12949/12704_fsm
base/12949/12711_vm
base/12949/12711_fsm
base/12949/12722_vm
base/12949/12722_fsm
base/12949/12735_vm
base/12949/12735_fsm
base/12949/12739_vm
base/12949/12739_fsm
base/12949/12743_vm
base/12949/12743_fsm
base/12949/12747_vm
base/12949/12747_fsm
base/12949/12751_vm
base/12949/12751_fsm
base/12949/12755_vm
base/12949/12755_fsm
base/12949/12760_vm
base/12949/12760_fsm
base/12949/12764_vm
base/12949/12764_fsm
base/12949/12774_vm
base/12949/12774_fsm
base/12949/12776_vm
base/12949/12776_fsm
base/12949/12793_vm
base/12949/12793_fsm
base/12949/12799_vm
base/12949/12799_fsm
base/12949/12808_vm
base/12949/12808_fsm
base/12949/12812_vm
base/12949/12812_fsm
base/12949/12817_vm
base/12949/12817_fsm
base/12949/12852_vm
base/12949/12852_fsm
base/12949/12856_vm
base/12949/12856_fsm
base/12949/12859_vm
base/12949/12859_fsm
base/12949/12863_vm
base/12949/12863_fsm
base/12949/12867_vm
base/12949/12867_fsm
base/12949/12871_vm
base/12949/12871_fsm
base/12949/12903_vm
base/12949/12903_fsm
base/12949/12914_vm
base/12949/12914_fsm
base/12949/12919_vm
base/12949/12919_fsm
base/12949/12924_vm
base/12949/12924_fsm
base/12949/12934_vm
base/12949/12934_fsm
base/12949/12771_vm
base/12949/12771_fsm
base/12949/12909_vm
base/12949/12909_fsm
base/12949/12899_vm
base/12949/12899_fsm
base/12949/12929_vm
base/12949/12929_fsm
pg_tblspc/
pg_stat/
pg_stat_tmp/
pg_stat_tmp/global.stat
PG_VERSION
postgresql.conf
pg_hba.conf
pg_ident.conf
global/pg_control

[pguser@dev tmp]$ ls /tmp/archivedir/
000000010000000000000001  000000010000000000000002.00000028.backup
000000010000000000000002  000000010000000000000003

[pguser@dev tmp]$ cat recovery.conf 
restore_command = 'cp /tmp/archivedir/%f "%p"'
recovery_target_time = '2014-11-28 17:54:26.212748+09'

[pguser@dev tmp]$ cp recovery.conf pgdata/

[pguser@dev tmp]$ pg_ctl -D pgdata start
server starting
[pguser@dev tmp]$ LOG:  database system was interrupted; last known up at 2014-11-28 17:53:47 JST
LOG:  creating missing WAL directory "pg_xlog/archive_status"
LOG:  starting point-in-time recovery to 2014-11-28 17:54:26.212748+09
LOG:  restored log file "000000010000000000000002" from archive
LOG:  redo starts at 0/2000090
LOG:  consistent recovery state reached at 0/20000B8
LOG:  restored log file "000000010000000000000003" from archive
LOG:  recovery stopping before commit of transaction 1892, time 2014-11-28 17:54:34.021328+09
LOG:  redo done at 0/30022A0
LOG:  last completed transaction was at log time 2014-11-28 17:54:17.830576+09
cp: `/tmp/archivedir/00000002.history' を stat できません: そのようなファイルやディレクトリはありません
LOG:  selected new timeline ID: 2
cp: `/tmp/archivedir/00000001.history' を stat できません: そのようなファイルやディレクトリはありません
LOG:  archive recovery complete
LOG:  database system is ready to accept connections
LOG:  autovacuum launcher started
LOG:  archive command failed with exit code 1
DETAIL:  The failed archive command was: test ! -f /tmp/archivedir/000000010000000000000003 && cp pg_xlog/000000010000000000000003 /tmp/archivedir/000000010000000000000003
LOG:  archive command failed with exit code 1
DETAIL:  The failed archive command was: test ! -f /tmp/archivedir/000000010000000000000003 && cp pg_xlog/000000010000000000000003 /tmp/archivedir/000000010000000000000003
LOG:  archive command failed with exit code 1
DETAIL:  The failed archive command was: test ! -f /tmp/archivedir/000000010000000000000003 &&  cp pg_xlog/000000010000000000000003 /tmp/archivedir/000000010000000000000003
WARNING:  archiving transaction log file "000000010000000000000003" failed too many times, will try again later

[pguser@dev tmp]$ psql -l
Timing is on.
Null display is "?".
Line style is unicode.
Border style is 2.
You are connected to database "postgres" as user "pguser" via socket in "/tmp" at port "5432".
                                List of databases
┌───────────┬─────────┬──────────┬────────────┬────────────┬─────────────────────┐
│   Name    │  Owner  │ Encoding │  Collate   │   Ctype    │  Access privileges  │
├───────────┼─────────┼──────────┼────────────┼────────────┼─────────────────────┤
│ db1       │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │                     │
│ db2       │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │                     │
│ db3       │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │                     │
│ postgres  │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │                     │
│ template0 │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │ =c/pguser         ?│
│           │         │          │            │            │ pguser=CTc/pguser │
│ template1 │ pguser │ UTF8     │ ja_JP.utf8 │ ja_JP.utf8 │ =c/pguser         ?│
│           │         │          │            │            │ pguser=CTc/pguser │
└───────────┴─────────┴──────────┴────────────┴────────────┴─────────────────────┘
(6 rows)

■ まとめ

PITR の設定はそれほど難しい物ではありませんが、アーカイブコマンドに間違いがある、アーカイブ先のディレクトリが存在しない、ディレクトリにアクセス権限がない、などの問題があると動作しません。これらのエラーは PostgreSQL のログファイルに記録されます。エラーメッセージを確認すると問題の原因が分かります。操作には慣れておかないといざという時に落ち着いて対処できないと思います。何度かリカバリを試しておくと良いでしょう。

PITR はデータベース操作ミスなどで誤ってデータベースを壊してしまった時の復旧には欠かせません。アーカイブログをコピーするだけなのでオーバーヘッドは小さいです。万が一の場合に備えて、PITR を設定しておくとより安全です。

ベースバックアップを取得してからの時間が長くなればなるほど、データ量も大きくなり、リカバリ時間も長くなります。データ容量を考えながら、ベースバックアップを取得する頻度とアーカイブログの取得を調整すると良いでしょう。

0 件のコメント:

コメントを投稿