sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLの増分バックアップとポイントインタイムリカバリ

    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、バーマン

    1. Git分岐命名規則:ベストプラクティス

    2. オフライン国際化アプリを作成する方法:Sqliteデータベースを使用する

    3. PHPで高精度の小数を操作するにはどうすればよいですか

    4. PlanetScale&Vitess:レガシーシャードデータベースによる参照整合性