PostgreSQLのマルチ同期レプリケーション


<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/PostgreSQL?src=hash">#PostgreSQL</a> にもついにマルチ同期レプリケーション入りました！<br>いい感じの設定方法をぜひお試しください！また将来の拡張にもぜひご期待ください！ <a href="https://t.co/Kv59MKGJxp">https://t.co/Kv59MKGJxp</a></p>&mdash; Masahiko Sawada (@sawada_masahiko) <a href="https://twitter.com/sawada_masahiko/status/717647588502056960">2016年4月6日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

PostgreSQLの開発版にマルチ同期レプリケーションが入りました。
上記のTweetにも書いてあるように設定方法がいい感じ(ちょっと複雑?)なので、これまでのレプリケーションと共に、いち早く紹介します。

# 9.5までの同期レプリケーションの設定
同期レプリケーションを設定するには、非同期レプリケーションの設定(マスタ側でのwal_levelやmax_wal_senders、スタンバイ側の設定)に加えて[synchronous_standby_names](https://www.postgresql.jp/document/9.5/html/runtime-config-replication.html#runtime-config-replication-master)をマスタサーバ側で設定する必要があります。

synchronous_standby_namesは同期スタンバイとして扱うスタンバイ名をカンマ区切りで以下のように列挙します。

```
synchronous_standby_names = 'standby1, standby2, standby3'
```

これらのスタンバイには左から順に優先度が１、２、３のように付けられるので、上記の様に設定すると、**優先度の高い一つだけ**が(つまりstnadby1のみが)、最初に同期スタンバイとして扱われ、優先度の高い同期スタンバイが落ちると自動的に次に優先度の高い(右隣の)スタンバイstandby2が同期スタンバイに昇格します。

##設定例(9.5)

`synchronous_standby_names = 'standby1, standby2, standby3'`と設定した場合、standby1 → standby2 → standby3の順に優先度が高く、上位１つのスタンバイが同期スタンバイとして扱われます。

pg_stat_replicationビューを見ることで同期/非同期スタンバイの状態が分かります。

```sql:
postgres=# SELECT application_name, sync_priority, sync_state FROM pg_stat_replication;
 application_name | sync_priority | sync_state
------------------+---------------+------------
 standby1         |             1 | sync
 standby2         |             2 | potential
 standby3         |             3 | potential
```

一番優先度の高い(一番左に列挙されている)standby1のみが同期スタンバイになっていることがわかります。

# 9.6からの同期レプリケーションの設定
9.6からはマルチ同期レプリケーションをサポートしています。
「何台のスタンバイを同期スタンバイとするか」を設定するために、PostgreSQLでは以下の様な**独自の構文**を使ってそれを表現します。

```
synchronous_standby_names = 'k (standby1, standby2, ... , standbyN )'
```

`standby1 ... standbyN` は9.5までと同様に同期スタンバイとして扱うスタンバイ名をカンマ区切りで列挙し、これまでと同じように１から順に優先度が付けられます。
`k`は「優先度の高いk台を同期スタンバイとして扱う」という意味になります。

## 設定例(9.6)

`synchronous_standby_names = '2 (standby1, standby2, standby3)'`と設定した場合、優先度上位２つスタンバイが同期スタンバイとして扱われます。

pg_stat_replicationビューを見てみましょう。

```sql:
postgres=# SELECT application_name, sync_priority, sync_state FROM pg_stat_replication;
 application_name | sync_priority | sync_state
------------------+---------------+------------
 standby1         |             1 | sync
 standby2         |             2 | sync
 standby3         |             3 | potential
```

standby1, standby2の２つが同期スタンバイになっていることがわかります。
この状態でstandby1が停止すると、代わりにstandby3が同期スタンバイに昇格し、pg_stat_replicationビューは以下の様になります。

```sql:
postgres=# SELECT application_name, sync_priority, sync_state FROM pg_stat_replication;
 application_name | sync_priority | sync_state
------------------+---------------+------------
 node2            |             2 | sync
 node3            |             3 | sync
(2 rows)
```

#まとめ
PostgreSQL開発版(9.6)に入ったマルチ同期レプリケーションを紹介しました。
開発版のソースコードは以下から取得できるので、ぜひお試しください。
- [git://git.postgresql.org/git/postgresql.git](git://git.postgresql.org/git/postgresql.git) (オリジナルのレポジトリ)
- https://github.com/postgres/postgres (githubにあるミラー)