PostgreSQLには、すぐに使用できる増分バックアップとポイントインタイムリカバリを実行する機能が付属しています。これを実現するための設定と手順の詳細については、以下をお読みください。
WALファイルで始まります
WAL 先行書き込みログの略です 。 WALは、耐久性のあるアトミックトランザクションを提供するために、ほぼすべての最新のRDBMSシステムで使用されています。
単一のPostgreSQLサーバープロセスによって管理されるPostgreSQLデータベースクラスターに含まれるデータへの変更は、トランザクションを介してのみ可能です。トランザクションによってデータに加えられた変更は、WALレコードの順序付けられたシーケンスとして記録されます。 。これらのレコードは、WALセグメントファイルと呼ばれる固定長のファイルに書き込まれます。 、または単にWALファイル 。
WALファイルは$PGDATA/pg_wal
にあります 、ここで$PGDATA
データベースクラスタのデータディレクトリです。たとえば、デフォルトのDebianインストールでは、メインクラスタのWALファイルディレクトリは/var/lib/postgresql/10/main/pg_wal
です。 。見た目は次のとおりです:
# pwd
/var/lib/postgresql/10/main/pg_wal
# ls -l
total 278532
-rw------- 1 postgres postgres 16777216 May 7 08:48 00000001000000000000000B
-rw------- 1 postgres postgres 16777216 May 7 10:08 00000001000000000000000C
-rw------- 1 postgres postgres 16777216 May 7 10:08 00000001000000000000000D
-rw------- 1 postgres postgres 16777216 May 7 10:08 00000001000000000000000E
-rw------- 1 postgres postgres 16777216 May 7 10:08 00000001000000000000000F
-rw------- 1 postgres postgres 16777216 May 7 10:08 000000010000000000000010
-rw------- 1 postgres postgres 16777216 May 7 10:08 000000010000000000000011
-rw------- 1 postgres postgres 16777216 May 7 10:08 000000010000000000000012
-rw------- 1 postgres postgres 16777216 May 7 10:08 000000010000000000000013
-rw------- 1 postgres postgres 16777216 May 7 10:08 000000010000000000000014
-rw------- 1 postgres postgres 16777216 May 7 10:08 000000010000000000000015
-rw------- 1 postgres postgres 16777216 May 7 10:08 000000010000000000000016
-rw------- 1 postgres postgres 16777216 May 7 10:08 000000010000000000000017
-rw------- 1 postgres postgres 16777216 May 16 20:52 000000010000000000000018
-rw------- 1 postgres postgres 16777216 May 16 20:56 000000010000000000000019
-rw------- 1 postgres postgres 16777216 May 26 08:52 00000001000000000000001A
-rw------- 1 postgres postgres 16777216 Jun 2 09:59 00000001000000000000001B
drwx------ 2 postgres postgres 4096 Mar 30 10:06 archive_status
WALファイルは、クラスターの作成から順番に段階的に生成されます。クラスターに変更が加えられる限り、それらは生成され続けます。 WALファイルメカニズムはPostgreSQLの動作に不可欠であり、オフにすることはできません。
変更が最初にWALレコードとして書き出された後、データ自体のディスク上の表現に適用する必要があります。このプロセスはチェックポイントと呼ばれます 、バックグラウンドで自動的に発生します(手動で強制することもできます)。チェックポイントが行われるまでのポイントは、REDOポイントと呼ばれます。 。チェックポインティングもPostgresアーキテクチャの重要な部分であり、オフにすることはできません。
WALファイルの保持
PostgreSQLサーバー操作の通常の過程では、WALファイルはpg_wal
に書き込まれ続けます ディレクトリ。しかし、なぜそれらを持っているのですか?
1つの理由はクラッシュリカバリです。 PostgreSQLサーバーがクラッシュして再起動すると、最後のREDOポイント以降、WALレコードからデータファイルへの変更の適用(チェックポイント)が開始されます。これにより、データファイルが最後に完了したトランザクションと整合性があることが保証されます。
もう1つの理由は、ストリーミングレプリケーションに関連しています。ストリーミングレプリケーションは、WALレコードをスタンバイに送信することで機能します これらをローカルに保存し、チェックポイントを実行するサーバー。スタンバイは、複製元のサーバー(プライマリと呼ばれます)に遅れをとることがあります )。たとえば、プライマリが100のWALレコードを生成し、スタンバイが最初の80を受信して適用した場合、スタンバイがレコード81以降を受信して適用できるように、最新の20が使用可能である必要があります。
しかし、確かに非常に古いWALファイルは削除できますか?はい。 PostgreSQLは、最新のWALファイルを保持し、古いファイルを削除するように指示できます。関連する構成オプションは3つあります。
- wal_keep_segments -WALファイルディレクトリに保持される最新のWALファイルの最小数を設定します
- max_wal_size -WALファイルディレクトリ内のWALファイルの最大合計サイズを指定します。これを超えると、古いものは削除されます。ただし、理由がある可能性があります(
wal_keep_segments
の値が高いなど) )この設定が尊重されないようにする可能性があります。 - min_wal_size -WALファイルの最小合計サイズを指定します。実際のサイズがこの値を下回っている限り、ファイルは削除されません。
実際には、以前のすべてのWALファイルをpg_wal
に保存することは不可能であるか、必須ではありません。 ディレクトリ。
WALファイルアーカイブ
WALファイルの真の価値は、変更のストリームであり、記録および再生してPostgreSQLクラスターの一貫したレプリカを取得できることです。PostgreSQLは、取得後に各WALファイルをコピー(または「アーカイブ」)できる方法を提供します。作成済み– archive_command 構成オプション。
このオプションは、各WALファイルが作成された後に呼び出されるシェルコマンド文字列を指定します。次にいくつかの例を示します。
# Copy the file to a safe location (like a mounted NFS volume)
archive_command = 'cp %p /mnt/nfs/%f'
# Not overwriting files is a good practice
archive_command = 'test ! -f /mnt/nfs/%f && cp %p /mnt/nfs/%f'
# Copy to S3 bucket
archive_command = 's3cmd put %p s3://BUCKET/path/%f'
# Copy to Google Cloud bucket
archive_command = 'gsutil cp %p gs://BUCKET/path/%f'
# An external script
archive_command = '/opt/scripts/archive_wal %p'
他にも2つのオプションがあり、設定する必要があります。
# this must be "on" to enable WAL archiving
archive_mode = on
# has to be "replica" (default) or "logical" for WAL archiving
wal_level = replica
WAL圧縮
WALファイルは、長期的で安全な保管場所にコピーする前に圧縮できます。ただし、 wal_compressionというオプションがあります 。これをオンにすると、PostgreSQLはWALファイル内の個々のWALレコードを圧縮します。 WALファイル自体は同じサイズ(通常は16 MB)ですが、プレーンレコードではなく一連の圧縮レコードが含まれます。
WALアーカイブは、連続アーカイブとも呼ばれます。 有効であり、増分バックアップ 。
この増分バックアップのプロセスを開始する前に、完全バックアップが必要です。これにより、WALファイルを増分バックアップできるベースラインが確立されます。完全バックアップは次のいずれかの方法で実行できます。
- Postgresサーバープロセスをシャットダウンしてクラスターデータディレクトリをコピーする(権限を保持しながら)、または
-
pg_basebackup
を使用する 実行中のPostgresサーバー上。
Point-In-Time-Recovery(PITR)
PITRとは、完全バックアップの復元から開始し、アーカイブされたWALファイルを指定されたタイムスタンプまで段階的にフェッチして適用するPostgreSQLの機能を指します。
これを行うには、restoredclusterデータディレクトリに「recovery.conf」というファイルを作成し、そのデータディレクトリのPostgresサーバーを起動する必要があります。recovery.confファイルにはターゲットタイムスタンプが含まれており、次のようになります。
>restore_command = 'cp /tmp/demo/archive/%f "%p"'
recovery_target_time = '2019-06-04 14:10:00'
restore_command PostgreSQLに必要なWALファイルをフェッチする方法を指定します。これはarchive_commandの逆です。 restorey_target_time 変更が必要になるまでの時間を指定します。
PostgreSQLサーバープロセスが起動してrecovery.confを検出したとき データディレクトリ内のファイルは、「リカバリモード」と呼ばれる特別なモードで起動します。リカバリモードの場合、クライアント接続は拒否されます。 PostgresはWALファイルをフェッチし、リカバリターゲット(この場合は指定されたタイムスタンプまで変更)が達成されるまでそれらを適用します。目標が達成されると、サーバーはデフォルトでWALの再生を一時停止します(他のアクションも可能です)。この時点で、復元の状態を調べ、すべてが正常に見える場合は、一時停止を解除してリカバリモードを終了し、通常の操作を続行する必要があります。
それはすべて理論とテキストの集まりでした。実際にどのように機能するかを試してみましょう。
まず、新しいクラスターを初期化します:
/tmp/demo$ pg_ctl -D clus1 initdb
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
The database cluster will be initialized with locale "C.UTF-8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".
Data page checksums are disabled.
creating directory clus1 ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... 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:
/usr/lib/postgresql/10/bin/pg_ctl -D clus1 -l logfile start
安全な保管場所として機能するディレクトリも作成します。これを「アーカイブ」と呼びましょう。
/tmp/demo$ mkdir archive
/tmp/demo$ ls -l
total 8
drwxr-xr-x 2 postgres postgres 4096 Jun 4 14:02 archive
drwx------ 19 postgres postgres 4096 Jun 4 14:02 clus1
サーバーを起動する前に、前に説明したアーカイブ設定を構成する必要があります。それでは、clus1/postgres.conf
の最後に以下を追加しましょう。 :
port = 6000
wal_level = logical
archive_mode = on
archive_command = 'cp %p /tmp/demo/archive/%f'
archive_timeout = 60
アーカイブコマンドは、WALファイルを以前に作成したアーカイブディレクトリにコピーするだけです。
archive_timeoutも追加しました 設定。通常、WALファイルは、16MBのWALファイルを満たすのに十分なWALレコードがある場合にのみ作成されます。これは、書き込みが少ないサーバーの場合、WALファイルが作成されるまで長時間待たなければならない可能性があることを意味します。 archive_timeoutを設定すると、Postgresに必須であることが通知されます。 いっぱいかどうかに関係なく、非常に多くの秒ごとにaWALファイルを作成します。
ここではこれを60(秒)に設定していますが、これはデモ専用です!通常、これほど低く抑えたくないでしょう。
「clus1」のコピーも作成しましょう。これは完全バックアップに相当します。
/tmp/demo$ cp -Rp clus1 clus2
/tmp/demo$ ls -l
total 12
drwxr-xr-x 2 postgres postgres 4096 Jun 4 14:02 archive
drwx------ 19 postgres postgres 4096 Jun 4 14:03 clus1
drwx------ 19 postgres postgres 4096 Jun 4 14:03 clus2
これでクラスターを開始できます:
/tmp/demo$ pg_ctl -D clus1 -l log1 start
waiting for server to start.... done
server started
いくつかのデータを追加しましょう。
/tmp/demo$ psql -h /var/run/postgresql -p 6000 postgres
psql (10.8 (Ubuntu 10.8-0ubuntu0.18.04.1))
Type "help" for help.
postgres=# create database demo;
CREATE DATABASE
postgres=# \c demo
You are now connected to database "demo" as user "postgres".
demo=# create table tbl1 (col1 int);
CREATE TABLE
demo=# insert into tbl1 (col1) select generate_series(1, 10000);
INSERT 0 10000
demo=# select count(*) from tbl1;
count
-------
10000
(1 row)
demo=# select now();
now
-------------------------------
2019-06-04 14:05:05.657871+00
(1 row)
demo=# \q
現在は14:05であることに注意してください。アーカイブコマンドが機能しているかどうかを確認しましょう:
/tmp/demo$ ls -l archive/
total 16384
-rw------- 1 postgres postgres 16777216 Jun 4 14:04 000000010000000000000001
はい、1つのアーカイブファイルがあります。最後の変更は14:05でした。数分待ってから、さらに変更を加えましょう。
/tmp/demo$ psql -h /var/run/postgresql -p 6000 demo
psql (10.8 (Ubuntu 10.8-0ubuntu0.18.04.1))
Type "help" for help.
demo=# select now();
now
-------------------------------
2019-06-04 14:16:06.093859+00
(1 row)
demo=# select count(*) from tbl1;
count
-------
10000
(1 row)
demo=# insert into tbl1 (col1) select generate_series(1, 100);
INSERT 0 100
demo=# select count(*) from tbl1;
count
-------
10100
(1 row)
demo=# \q
これで、14:16にさらに100行が追加されました。サーバーを停止しましょう:
/tmp/demo$ pg_ctl -D clus1 stop
waiting for server to shut down.... done
server stopped
/tmp/demo$
アーカイブをもう一度確認してください:
/tmp/demo$ ls -l archive/
total 65536
-rw------- 1 postgres postgres 16777216 Jun 4 14:04 000000010000000000000001
-rw------- 1 postgres postgres 16777216 Jun 4 14:05 000000010000000000000002
-rw------- 1 postgres postgres 16777216 Jun 4 14:09 000000010000000000000003
-rw------- 1 postgres postgres 16777216 Jun 4 14:16 000000010000000000000004
いいね。次に、14:10までにclus2のPITRリカバリを実行しようとします。
まず、clus2のpostgres.confを編集して、最後に次の行を追加しましょう:
port = 6001
archive_mode = off
WALファイルを再生するには、clus2用のPostgreSQLサーバー(まだ起動していません)をリカバリモードにする必要があります。これを行うには、clus2に「recovery.conf」というファイルを作成します。
/tmp/demo$ cat clus2/recovery.conf
restore_command = 'cp /tmp/demo/archive/%f "%p"'
recovery_target_time = '2019-06-04 14:10:00'
これにはrestore_commandが含まれています これは、以前の archive_commandの反対を行います つまり、要求されたファイルをアーカイブディレクトリからpg_walディレクトリにコピーします。
どのrecovery_target_timeも設定しました 14:10まで。
ここで、clus2を開始します:
/tmp/demo$ pg_ctl -D clus2 -l log2 start
waiting for server to start.... done
server started
何が起こったかを確認するために、ログファイルを調べてみましょう:
/tmp/demo$ cat log2
2019-06-04 14:19:10.862 UTC [10513] LOG: listening on IPv4 address "127.0.0.1", port 6001
2019-06-04 14:19:10.864 UTC [10513] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.6001"
2019-06-04 14:19:10.883 UTC [10514] LOG: database system was shut down at 2019-06-04 14:02:31 UTC
2019-06-04 14:19:10.883 UTC [10514] LOG: starting point-in-time recovery to 2019-06-04 14:10:00+00
2019-06-04 14:19:10.903 UTC [10514] LOG: restored log file "000000010000000000000001" from archive
2019-06-04 14:19:10.930 UTC [10514] LOG: consistent recovery state reached at 0/16383E8
2019-06-04 14:19:10.930 UTC [10514] LOG: redo starts at 0/16383E8
2019-06-04 14:19:10.931 UTC [10513] LOG: database system is ready to accept read only connections
2019-06-04 14:19:11.037 UTC [10514] LOG: restored log file "000000010000000000000002" from archive
2019-06-04 14:19:11.079 UTC [10514] LOG: restored log file "000000010000000000000003" from archive
2019-06-04 14:19:11.122 UTC [10514] LOG: restored log file "000000010000000000000004" from archive
2019-06-04 14:19:11.141 UTC [10514] LOG: recovery stopping before commit of transaction 559, time 2019-06-04 14:16:24.875517+00
2019-06-04 14:19:11.141 UTC [10514] LOG: recovery has paused
2019-06-04 14:19:11.141 UTC [10514] HINT: Execute pg_wal_replay_resume() to continue.
回復は迅速で(実際には、数時間または数日かかる場合があります)、特定のトランザクションの前に停止したログ状態(タイムスタンプが14:10を超える)があります。また、リカバリが一時停止されており、手動で続行する必要があることも示されています。
データを調べてみましょう:
/tmp/demo$ psql -h /var/run/postgresql -p 6001 demo
psql (10.8 (Ubuntu 10.8-0ubuntu0.18.04.1))
Type "help" for help.
demo=# select count(*) from tbl1;
count
-------
10000
(1 row)
10000行しかないことがわかります。 14:16に、テーブルに表示されていない100を追加しました。
これは良さそうなので、再開しましょう:
demo=# select pg_wal_replay_resume();
pg_wal_replay_resume
----------------------
(1 row)
ログファイルは、リカバリが完了し、通常の操作が復元されたことを報告します。
2019-06-04 14:20:26.219 UTC [10514] LOG: redo done at 0/4002160
2019-06-04 14:20:26.219 UTC [10514] LOG: last completed transaction was at log time 2019-06-04 14:05:28.813325+00
cp: cannot stat '/tmp/demo/archive/00000002.history': No such file or directory
2019-06-04 14:20:26.228 UTC [10514] LOG: selected new timeline ID: 2
2019-06-04 14:20:26.272 UTC [10514] LOG: archive recovery complete
cp: cannot stat '/tmp/demo/archive/00000001.history': No such file or directory
2019-06-04 14:20:26.388 UTC [10513] LOG: database system is ready to accept connections
そして、指定された時間までクラスターを正常に回復しました!
WALアーカイブ、リカバリモード、PITRについて詳しく知るための、いくつかの出発点を次に示します。
- ドキュメント:RecoveryConfiguration
- ドキュメント:継続的なアーカイブとPITR
- 「TheInternalsofPostgreSQL」の本の第9章
- ツール:WAL-E、WAL-G、バーマン