2012年12月14日

pg_receivexlogでリアルタイムバックアップを取得する

PostgreSQL Advent Calendar 2012(全部俺)のDay 14です。

ご存じのように、PostgreSQLは9.0から標準でレプリケーションが実装されました。それに加えて9.2では、pg_receivexlogというコマンドが追加されました。

pg_receivexlog
http://www.postgresql.jp/document/9.2/html/app-pgreceivexlog.html

pg_receivexlogは、ネットワーク経由でトランザクションログを受信、ログのアーカイブを作成・蓄積していくことを可能にするコマンドです。このコマンドを使うことによってスタンバイサーバを稼働していなくても、レプリケーションの機能を使ってリアルタイムバックアップを取得することができるようになります。

pg_receivexlogの基本的な仕組みについては、ストリーミングレプリケーションの開発者のFujii氏の以下のスライドを参照してください。


今回は、このpg_receivexlogコマンドを使ってアーカイブログを別サーバに蓄積し、それを使ってリカバリができるのか、というところを検証してみようと思います。

なお、Fujii氏のエントリと盛大に被ってしまったのですが、ここでは気にしないことにします。氏のエントリも併せて読むと二倍楽しめるかもしれません。

■検証構成


今回は以下のような環境でpg_receivexlogの検証を実施しました。

マスターサーバ、スタンバイサーバのいずれもAmazon EC2でLInux AMIインスタンスを利用し、同一リージョン内でWAL転送する構成としています。

マスターサーバ(PostgreSQLを稼働するサーバ)
  • Amazon EC2 Linux AMI (32bit)
  • PostgreSQL 9.2
  • IPアドレス:10.156.93.165

スタンバイサーバ(pg_receivexlog稼働してWALを受信するサーバ)
  • Amazon EC2 Linux AMI (32bit)
  • PostgreSQL 9.2
  • IPアドレス:10.146.98.58
  • 受信したWALを蓄積するディレクトリ:/var/lib/pgsql/9.2/receivexlog/
  • ベースバックアップを取得するディレクトリ:/var/lib/pgsql/9.2/receivebase/
Amazon EC2におけるPostgreSQLサーバの基本的な構築方法については今回は割愛します。詳細はDay13のエントリを参照してください。

■pg_receivexlogのための設定項目


今回、pg_receivexlogを使うために追加で設定した項目は以下の通りです。

postgresql.confでは設定したのは以下の4つの項目です。
wal_level = archive
archive_command = 'cat /dev/null'
max_wal_senders = 3
wal_keep_segments = 8
アーカイブログとしてWALを生成しますのでwal_levelはarchiveとします。

今回はPostgreSQL稼働サーバ上ではアーカイブログを取得しませんが、archive_commandが設定されていないとベースバックアップの取得ができないため、archive_commandはダミーコマンドを設定します。

PostgreSQL稼働サーバ上にWAL送信プロセスが必要ですので、max_wal_sendersを3とします。

pg_receivexlogでの受信が遅延した場合、WALセグメントファイル8つ分までは追い付くことが可能な設定とします(ここでの8は適当な値です)。

次に、レプリケーションの接続を受け付けるためにpg_hba.confに設定を追加します。ここで指定している "10.146.98.58" はスタンバイサーバ(pg_receivexlogを稼働させるサーバ)のIPアドレスです。
hostssl replication     postgres        10.146.98.58/32         trust

■リアルタイムバックアップを開始する


設定が完了したら、まずはPostgreSQLを起動します。

PostgreSQLが稼働し始めたら、スタンバイサーバ上でpg_receivexlogコマンドを起動してWALの受信を開始します。
-bash-4.1$ /usr/pgsql-9.2/bin/pg_receivexlog -h 10.156.93.165 -p 6453 -U postgres -D /var/lib/pgsql/9.2/receivexlog -v
pg_receivexlog: starting log streaming at 0/A000000 (timeline 1)
pg_receivexlogコマンドを実行する際には、マスターとなるPostgreSQLサーバのIPアドレス、ポート番号、接続ユーザ名、および受信したWALを保存するローカルのディレクトリを指定します。

"starting log streaming" というメッセージが出たら、ログの受信の開始は成功です。その時、受信用のディレクトリを見ると、
[root@ip-10-146-98-58 ~]# ls -al /var/lib/pgsql/9.2/receivexlog/
total 16392
drwxr-xr-x 2 postgres postgres     4096 Dec  6 14:40 .
drwx------ 5 postgres postgres     4096 Dec  6 14:33 ..
-rw------- 1 postgres postgres 16777216 Dec  6 14:40 00000001000000000000000A.partial
[root@ip-10-146-98-58 ~]# 
という形でファイルができ始めていることが分かります。

ここで作成されているファイルの末尾には「.partial」という suffix が付いています。どうやら、まだ16MBを使い切っていない利用中のWALファイル(セグメントファイル)については末尾に「.partial」という suffix が付加されるようです。

ここで、PostgreSQLに対して(WALを生成するために)データの更新処理を行ってみます。
-bash-4.1$ /usr/pgsql-9.2/bin/pgbench -p 6453 -s 10 -i testdb
この時に受信ディレクトリを見てみると、
[root@ip-10-146-98-58 ~]# ls -al /var/lib/pgsql/9.2/receivexlog/
total 131080
drwxr-xr-x 2 postgres postgres     4096 Dec  6 14:43 .
drwx------ 5 postgres postgres     4096 Dec  6 14:33 ..
-rw------- 1 postgres postgres 16777216 Dec  6 14:42 00000001000000000000000A
-rw------- 1 postgres postgres 16777216 Dec  6 14:42 00000001000000000000000B
-rw------- 1 postgres postgres 16777216 Dec  6 14:42 00000001000000000000000C
-rw------- 1 postgres postgres 16777216 Dec  6 14:42 00000001000000000000000D
-rw------- 1 postgres postgres 16777216 Dec  6 14:42 00000001000000000000000E
-rw------- 1 postgres postgres 16777216 Dec  6 14:42 00000001000000000000000F
-rw------- 1 postgres postgres 16777216 Dec  6 14:43 000000010000000000000010
-rw------- 1 postgres postgres 16777216 Dec  6 14:43 000000010000000000000011.partial
[root@ip-10-146-98-58 ~]#
WALセグメントファイルが作成されており、WALが継続的に保存されていることが分かります。

■バックアップセットを取ってみる


それでは、ここでpg_receivexlogで取得したアーカイブログを使ったリカバリを試してみます。

まず、先ほどと同じようにログの受信を開始します。
bash-4.1$ /usr/pgsql-9.2/bin/pg_receivexlog -h 10.156.93.165 -p 6453 -U postgres -D /var/lib/pgsql/9.2/receivexlog -v
pg_receivexlog: starting log streaming at 0/19000000 (timeline 1)
ログの蓄積が開始されたら、次にベースバックアップを取得します。

今回は、pg_basebackupコマンドを使ってネットワーク経由でスタンバイサーバ上にベースバックアップを取得します。ここでは、一旦 /var/lib/pgsql/9.2/receivebase ディレクトリにベースバックアップを保存します。
-bash-4.1$ /usr/pgsql-9.2/bin/pg_basebackup  -h 10.156.93.165 -p 6453 -U postgres -D /var/lib/pgsql/9.2/receivebase -v
NOTICE:  pg_stop_backup complete, all required WAL segments have been archived
pg_basebackup: base backup completed
-bash-4.1$
ベースバックアップを取得したら、ベースバック取得以降のWALを生成するために、データを更新処理を行います。
[snaga@db01 ~]$ psql -p 6453 testdb
psql (9.2.1)
Type "help" for help.

testdb=> \d
               List of relations
 Schema |        Name        | Type  |  Owner
--------+--------------------+-------+----------
 public | pg_stat_statements | view  | postgres
 public | pgbench_accounts   | table | postgres
 public | pgbench_branches   | table | postgres
 public | pgbench_history    | table | postgres
 public | pgbench_tellers    | table | postgres
 public | t1                 | table | postgres
 public | t2                 | table | snaga
(7 rows)

testdb=> create table t3 ( uid integer primary key, uname text not null );
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "t3_pkey" for table "t3"
CREATE TABLE
testdb=> insert into t3 values ( 101, 'Jung, Nicole' );
INSERT 0 1
testdb=>
ここで、CTRL-Cでpg_receivexlogコマンドを停止します。
bash-4.1$ /usr/pgsql-9.2/bin/pg_receivexlog -h 10.156.93.165 -p 6453 -U postgres -D /var/lib/pgsql/9.2/receivexlog -v
pg_receivexlog: starting log streaming at 0/19000000 (timeline 1)
pg_receivexlog: finished segment at 0/1A000000 (timeline 1)
^Cpg_receivexlog: received interrupt signal, exiting.
pg_receivexlog: not renaming "00000001000000000000001A", segment is not complete
bash-4.1$
pg_receivexlogコマンドの停止によって、スタンバイからマスターへの接続が完全に切断され、マスターサーバからスタンバイサーバへのログのストリーミングが停止します。

■アーカイブログリカバリを実施


この状態で、先ほどまでに取得してあったバックアップセットを使ってスタンバイノード上にレストア、リカバリを実施してみます。

使用するのは、ベースバックアップと、リアルタイムにバックアップを取ってあったアーカイブログです。

まず、取得してあったベースバックアップをスタンバイサーバに展開します。
-bash-4.1$ pwd
/var/lib/pgsql
-bash-4.1$ ls -F
9.2/
-bash-4.1$ cd 9.2/
-bash-4.1$ ls -F
backups/  data/  receivebase/  receivexlog/
-bash-4.1$ ls data/
-bash-4.1$ cp -r receivebase/* data/
-bash-4.1$ ls -F data
backup_label  pg_ident.conf  pg_snapshots/  PG_VERSION            server.key
base/         pg_log/        pg_stat_tmp/   pg_xlog/
global/       pg_multixact/  pg_subtrans/   postgresql.conf
pg_clog/      pg_notify/     pg_tblspc/     postgresql.conf.orig
pg_hba.conf   pg_serial/     pg_twophase/   server.crt
次に蓄積していたアーカイブログをpg_xlog以下に配置します。「.partial」と suffix の付いていたWALセグメントファイルも、通常のWALセグメントのファイル名に変更します。
-bash-4.1$ cp receivexlog/0000000100000000000000* data/pg_xlog/
-bash-4.1$ cd data/pg_xlog/
-bash-4.1$ ls -F
00000001000000000000000A  000000010000000000000013
00000001000000000000000B  000000010000000000000014
00000001000000000000000C  000000010000000000000015
00000001000000000000000D  000000010000000000000016
00000001000000000000000E  000000010000000000000017
00000001000000000000000F  000000010000000000000018
000000010000000000000010  000000010000000000000019
000000010000000000000011  00000001000000000000001A.partial
000000010000000000000012
-bash-4.1$ mv 00000001000000000000001A.partial 00000001000000000000001A
-bash-4.1$ pwd
/var/lib/pgsql/9.2/data/pg_xlog
-bash-4.1$
ここまで準備ができたら、スタンバイサーバのPostgreSQLを起動します。
[root@ip-10-146-98-58 ~]# /etc/rc.d/init.d/postgresql-9.2 start
Starting postgresql-9.2 service:                           [  OK  ]
[root@ip-10-146-98-58 ~]#
スタンバイサーバ上でPostgreSQLサービスが正しく起動したら、データベースインスタンスに接続してレコードを見てみます。
[root@ip-10-146-98-58 ~]# su - postgres
-bash-4.1$ psql testdb
psql (9.2.1)
Type "help" for help.

testdb=# \d
               List of relations
 Schema |        Name        | Type  |  Owner
--------+--------------------+-------+----------
 public | pg_stat_statements | view  | postgres
 public | pgbench_accounts   | table | postgres
 public | pgbench_branches   | table | postgres
 public | pgbench_history    | table | postgres
 public | pgbench_tellers    | table | postgres
 public | t1                 | table | postgres
 public | t2                 | table | snaga
 public | t3                 | table | snaga
(8 rows)

testdb=# select * from t3;
 uid |    uname
-----+--------------
 101 | Jung, Nicole
(1 row)

testdb=#
先ほど、ベースバックアップ取得以降に更新を行ったレコード(最後にINSERTしたもの)までリカバリできていることが分かります。

この時のサーバログを見ると、
[2012-12-07 00:10:14 JST] 4197: LOG:  database system was interrupted; last known up at 2012-12-07 00:00:16 JST
[2012-12-07 00:10:14 JST] 4197: LOG:  creating missing WAL directory "pg_xlog/archive_status"
[2012-12-07 00:10:14 JST] 4197: LOG:  database system was not properly shut down; automatic recovery in progress
[2012-12-07 00:10:14 JST] 4197: LOG:  redo starts at 0/19000074
[2012-12-07 00:10:14 JST] 4197: LOG:  record with zero length at 0/1A023DEC
[2012-12-07 00:10:14 JST] 4197: LOG:  redo done at 0/1A023DC4
[2012-12-07 00:10:14 JST] 4197: LOG:  last completed transaction was at log time 2012-12-07 00:04:39.920898+09
[2012-12-07 00:10:14 JST] 4194: LOG:  database system is ready to accept connections
となっていて、通常のWALと同じようにリカバリすることができていることが分かります。

■まとめ


今回は、バージョン9.2で新たに追加されたpg_receivexlogコマンドを使って、ネットワーク経由でのアーカイブログのリアルタイムバックアップ、そしてそこからリカバリできるかどうかを試してみました。

実際に実運用するためには手順として考えなければならないことはもう少しあるかと思いますが、機能として動作するところまでは今回確認することができました。

データベースの最大の役割のひとつは「データの保護」にあります(少なくとも私はそう思っています)。そういった意味でも、このpg_receivexlogコマンドのような機能は、今後の活躍が期待される領域のひとつのように思います。

では、また。

0 件のコメント:

コメントを投稿