PostgreSQL 9.5 によるレプリケーション構成（非同期）

今回はVM2台を使用したPostgreSQLのレプリケーション環境の構築手順について説明します。

# 前提
- VirtualBoxでVMを2台使用します。
- 2台のVMでは、CentOS 7で[PostgreSQLのインストール手順](http://qiita.com/U_ikki/items/21242bc6497ed12e82e7)の「3-1. ~/.bash_profileを編集」まで実施します
- マスタとして構築するVMでは「3-2. DBクラスタ作成」まで実施します。

以降の作業は全てpostgresユーザを使用します。

# 1. PostgreSQLの設定ファイルを修正する（マスタのみで実施）
## 1-1. postgresql.conf
レプリケーション用に設定ファイルを修正します。
レプリケーションを行う上で必須なのは　**wal_level, max_wal_sender**　の設定です。

```postgresql.conf
# Add settings for extensions here
listen_addresses = '*'
checkpoint_timeout = 15min
hot_standby = on
logging_collector = on
log_filename = 'postgresql-%Y-%m-%d.log'        
log_min_duration_statement = 60 
log_checkpoints = on
log_lock_waits = on
log_error_verbosity = verbose
log_line_prefix = '%m [%p] '

wal_level = hot_standby
max_wal_senders = 3     
```

**wal_level**
WALに出力される情報を制御するための設定です。
下に行くほど、書き出される情報量は増えていきます。

| wal_level | 説明 |
|:----------|:----|
|minial|クラッシュリカバリのみが実施できる|
|archive|minimalに加え、[PITR](http://www.postgresql.jp/document/9.5/html/continuous-archiving.html)、ストリーミングレプリケーションを実施できる。**9.6からは'replica'に変更**|
|hot_standby|archiveに加え、[ホットスタンバイ](http://www.postgresql.jp/document/9.5/html/hot-standby.html)を実施できる。**9.6からは'replica'に変更**|
|logical|hot_standbyに加え、WALの復号化を実施できる。|

※なお、PostgreSQL9.6（2016年9月リリース）では、「archive」と「hot_standby」が新しい「replica」に統合されました。

**wal_sender**
DBサーバで起動するwal_senderプロセスの最大数を制御します。
デフォルトは「0」になっているので、レプリケーションを行うのであれば「1」以上を設定する必要があります。
なぜ、レプリケーションでwal_senderが必要になるのかは[レプリケーションの仕組み](http://qiita.com/U_ikki/items/2d01bee76c0d2935cf7b)で簡単に説明していますので良ければ参考にしてください。

## 1-2. pg_hba.conf
レプリケーションに必要な認証の設定をします。
フォーマットは以下のとおり。詳細は[マニュアル](https://www.postgresql.jp/document/9.5/html/auth-pg-hba-conf.html)を参照してください。
接続形式、接続先のデータベース名、DBロール、クライアントのIPアドレス範囲、認証方法

```pg_hba.conf
host    replication     postgres        192.168.1.0/24            trust
```

DB名「replication」はレプリケーション接続を許容するための特殊な設定です。

# 2. PostgreSQLを起動する（マスタのみで実施）
pg_ctlコマンドを使用して、データベースを起動します。

```
$ pg_ctl start
server starting
2016-05-27 21:52:51.360 JST [18403] LOG:  00000: redirecting log output to logging collector process
2016-05-27 21:52:51.360 JST [18403] HINT:  Future log output will appear in directory "pg_log".
2016-05-27 21:52:51.360 JST [18403] LOCATION:  SysLogger_Start, syslogger.c:622
```

# 3. ベースバックアップを取得する（スレーブのみで実施）
PostgreSQLが提供するpg_basebackupコマンドを使用してベースバックアップを取得します。
pg_basebackupによりマスタの＄PGDATA配下のファイルがスレーブに複製されます。

```
$ pg_basebackup -h 192.168.1.1 -D $PGDATA -X stream --progress -U postgres -R 
22535/22535 kB (100%), 1/1 tablespace
$ ls -l $PGDATA
total 56
-rw-------. 1 postgres postgres   206  5月 27 22:22 backup_label
drwx------. 5 postgres postgres    38  5月 27 22:22 base
drwx------. 2 postgres postgres  4096  5月 27 22:22 global
drwx------. 2 postgres postgres    17  5月 27 22:22 pg_clog
・・・
-rw-------. 1 postgres postgres 22024  5月 27 22:22 postgresql.conf
-rw-r--r--. 1 postgres postgres   134  5月 27 22:22 recovery.conf
```

# 4. recovery.confを作成する（スレーブのみで実施）
＄PGDATA配下にrecovery.confを作成します。
recovery.confはリカバリの指示を行うためのスレーブの設定ファイルです。

```$PGDATA/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=postgres host=192.168.1.1 port=5432'
```

# 5. PostgreSQLを起動する（スレーブのみで実施）
スレーブを起動し、レプリケーションを開始します。

```
$ pg_ctl start
server starting
2016-05-27 22:53:42.384 JST [16564] LOG:  00000: redirecting log output to logging collector process
2016-05-27 22:53:42.384 JST [16564] HINT:  Future log output will appear in directory "pg_log".
2016-05-27 22:53:42.384 JST [16564] LOCATION:  SysLogger_Start, syslogger.c:622
```

# 6. レプリケーションが開始されたことの確認（マスタのみで実施）
PostgreSQLの統計情報ビュー「pg_stat_replication」を参照することで、レプリケーション状況を確認することができます。

```
$ psql postgres -c "SELECT * FROM pg_stat_replication" -x
-[ RECORD 1 ]----+------------------------------
pid              | 19705
usesysid         | 10
usename          | postgres
application_name | walreceiver
client_addr      | 192.168.1.2
client_hostname  | 
client_port      | 51074
backend_start    | 2016-05-27 22:53:42.626796+09
backend_xmin     | 
state            | streaming
sent_location    | 0/3000220
write_location   | 0/3000220
flush_location   | 0/3000220
replay_location  | 0/3000220
sync_priority    | 0
sync_state       | async
```

192.168.1.2とsync_state：async（非同期）のレプリケーション接続されていることを確認できます。
pg_stat_replicationの詳細は[マニュアル](http://www.postgresql.jp/document/9.5/html/monitoring-stats.html#pg-stat-replication-view)を確認してください。

# 7. レプリケーションされたデータを確認する
マスタのテーブルを更新してスレーブに反映されるか確認します。

## 7-1. データを挿入する（マスタのみで実施）

```
$ psql postgres -c "CREATE TABLE test_table(i int)"
CREATE TABLE
$ psql postgres -c "INSERT INTO test_table VALUES (1)"
INSERT 0 1
$ psql postgres -c "SELECT * FROM test_table"
 i 
---
 1
(1 row)
```

ちゃんとマスタにデータが入力されていますね。
スレーブのデータはどうでしょうか？

## 7-2. 挿入したデータを参照する（スレーブのみで実施）
今回の設定ではwal_level=hot_standbyにしているので、スレーブに対して参照処理を実施することができます。

```
$ psql postgres -c "SELECT * FROM test_table"
 i 
---
 1
(1 row)
```

ちゃんとレプリケーションされていることを確認できました。
設定は簡単ですね。

次は同期レプリケーションの設定方法と注意点について書きましょうか。