目次を表示する

RDB内部構造完全ガイド

レプリケーション ── ストリーミング・ロジカル

レプリケーション ── ストリーミング・ロジカル

このレイヤーの役割:データを複数のサーバーにコピーし、読み取りスケールアウト・高可用性・災害対策を実現する。


レプリケーション — ストリーミング・ロジカル・同期/非同期

この章で何ができるようになるか:ストリーミングレプリケーションとロジカルレプリケーションの仕組みと使い分けを理解し、レプリケーション遅延の原因と対策を説明できるようになる。


2種類のレプリケーション

ストリーミングレプリケーション(物理レプリケーション)

WAL をそのままレプリカに転送して適用する。バイトレベルの完全コピー。

Primary → WAL → Replica(全く同じバイト列を持つ)

特徴:
  ✅ セットアップが簡単
  ✅ 全てのデータが自動的にレプリケートされる
  ✅ レプリカでの適用が高速(WAL を再生するだけ)
  ❌ PostgreSQL のメジャーバージョンが一致する必要
  ❌ テーブル単位の選択的レプリケーションはできない
  ❌ レプリカは完全に読み取り専用(書き込み不可)
-- Primary の設定(postgresql.conf)
wal_level = replica
max_wal_senders = 10
wal_keep_size = '1GB'

-- Replica の構築
pg_basebackup -h primary-host -D /var/lib/postgresql/data -P -R
-- -R: standby.signal ファイルと primary_conninfo を自動設定

-- Replica の postgresql.conf
primary_conninfo = 'host=primary-host port=5432 user=replicator'
hot_standby = on  -- レプリカでの SELECT を許可

ロジカルレプリケーション(PostgreSQL 10+)

WAL を**論理的な変更(INSERT/UPDATE/DELETE)**にデコードして転送する。

Primary → WAL → Logical Decoder → INSERT/UPDATE/DELETE → Replica

特徴:
  ✅ テーブル単位で選択的にレプリケーション可能
  ✅ 異なる PostgreSQL バージョン間で動作
  ✅ レプリカに追加のインデックスやトリガーを設定可能
  ✅ レプリカに書き込み可能(双方向も原理上可能)
  ❌ DDL(ALTER TABLE 等)はレプリケーションされない
  ❌ 大きなテーブルの初期同期が遅い
  ❌ TRUNCATE は PostgreSQL 11+ でサポート
-- Primary: Publication の作成
CREATE PUBLICATION my_pub FOR TABLE users, orders;
-- または全テーブル:
CREATE PUBLICATION my_pub FOR ALL TABLES;

-- Replica: Subscription の作成
CREATE SUBSCRIPTION my_sub
    CONNECTION 'host=primary-host port=5432 dbname=mydb user=replicator'
    PUBLICATION my_pub;
-- → 初期データの同期が開始される
-- → その後はリアルタイムで変更が転送される

同期 vs 非同期レプリケーション

-- 非同期(デフォルト): Primary は WAL を書いたら即座にコミットを返す
synchronous_standby_names = ''

-- 同期: 少なくとも1台のレプリカが WAL を受信してからコミットを返す
synchronous_standby_names = 'FIRST 1 (replica1, replica2)'
-- → 書き込みレイテンシが増加するが、データロスのリスクがゼロ

-- 準同期: レプリカが WAL を受信(ディスクに書き込む前)でコミット
synchronous_commit = remote_write
-- → remote_apply(適用完了まで待つ)より速い
非同期同期
書き込みレイテンシ低い高い(ネットワーク RTT 分)
フェイルオーバー時のデータロスわずかにあり得るなし
レプリカ障害時の影響なしPrimary の書き込みがブロックされる

レプリケーション遅延の監視と対策

-- Primary 側: レプリカの遅延を確認
SELECT
    client_addr,
    state,
    sent_lsn,
    write_lsn,
    flush_lsn,
    replay_lsn,
    pg_wal_lsn_diff(sent_lsn, replay_lsn) AS replay_lag_bytes,
    reply_time
FROM pg_stat_replication;

-- Replica 側: 自分の遅延を確認
SELECT
    now() - pg_last_xact_replay_timestamp() AS replication_delay;
-- → 数秒以内なら正常。数分以上なら問題あり。

遅延の原因と対策

1. ネットワーク帯域不足
   → WAL の転送速度がネットワーク帯域を超えている
   → 対策: WAL 圧縮(wal_compression = on)

2. レプリカの I/O 性能不足
   → WAL の適用がディスク書き込みに律速
   → 対策: レプリカにも SSD を使う

3. レプリカの負荷(重い SELECT クエリ)
   → WAL 適用プロセスがリソースを取得できない
   → 対策: レプリカ上の重いクエリを制限

4. 長時間クエリとの競合
   → レプリカ上の SELECT が WAL 適用をブロック
   → hot_standby_feedback = on で VACUUM の遅延を通知
   → max_standby_streaming_delay = '30s'(30秒待ってからクエリをキャンセル)

フェイルオーバー

Primary が障害:
  1. レプリカを新 Primary に昇格(promote)
  2. アプリケーションの接続先を切り替え

手動昇格:
  pg_ctl promote -D /var/lib/postgresql/data

自動フェイルオーバー:
  Patroni(etcd ベース)
  pgpool-II
  repmgr
  → ヘルスチェック → 障害検知 → 自動昇格 → DNS/VIP 切り替え

まとめ

レプリケーション方式単位用途
ストリーミング(物理)DB 全体読み取りスケールアウト、HA
ロジカルテーブル単位選択的レプリケーション、異バージョン間
同期データロスゼロが必須の場合
非同期パフォーマンス優先