
1. Slony-I とは
Slony-I は古くからある PostgreSQL 専用のレプリケーションツールです。テーブル単位でデータ同期を取ることができます。
PostgreSQL 7.xや8.xの時代によく使われていましたが、PostgreSQL 9.0 でストリーミングレプリケーション機能が本体に標準付属するようになって、主役の座を譲り渡しました。さらに PostgreSQL 9.4 からロジカルデコーディングという行単位の更新内容を継続的に吐き出すことができる基盤機能が追加され、ロジカルデコーディング機能を活用した新たなレプリケーションツール(例えば pglogical)が登場しています。
しかしながら、Slony-I は現在でも、次のような場合に用途があります。
- 特定テーブルだけ、特定データベースだけ、レプリケーションしたい。しかし、PostgreSQL 9.3 バージョン以前なので、未だロジカルデコーディングによる方法は使えない。
- バージョンの異なる PostgreSQL 同士でデータ連携したい。特に比較的古いバージョンの PostgreSQL を含む場合。
- サービス停止時間を最小化して、古いバージョンの PostgreSQL をアップグレードしたい。特に、旧バージョンが pg_upgradeコマンドを適用できないバージョンやビルド設定であった場合。
以下の表にレプリケーションの手段の特徴を示します。
レプリケーション の手段 |
Slony-I 1.2 | Slony-I 2.x | ストリーミング レプリケーション |
pglogical 1.x |
対応する PostgreSQL バージョン |
7.4 から 8.4 まで | 8.3 以降 | 9.0 以降 | 9.4 以降 |
レプリケーション の単位 |
テーブル | テーブル | インスタンス | テーブル |
基盤となる仕組み | トリガー | トリガー | WAL データ転送 とリカバリ |
ロジカル デコーディング |
オーバーヘッド | 大きい | 大きい | 小さい | やや大きい |
2. 基本的なアーキテクチャ
Slony-I はトリガーベースのレプリケーションツールです。以下の図はその基本的なアーキテクチャを示したものです。
同期元テーブルに INSERT、UPDATE、DELETE、TRUNCATE があると、トリガーによってその更新内容がログテーブルに記録されます。更新ログテーブルはslon プロセスによって定期チェックされて、新たな更新があると、それを同期先テーブルに伝搬します。これらの処理を行うために対象テーブルには主キーが必要となります。また、トリガー対象外のラージオブジェクトは扱えません。
Slony-I は、同期元・同期先の両データベース上に更新ログテーブル以外にも各種状態情報や設定情報を格納する制御テーブル群を配置して使用します。また、slon プロセスは通常のデータベースクライアントとして振る舞いますが、トリガー関数や操作のための関数が一部においてC言語で実装されているため、PostgreSQL に共有ライブラリファイルの導入が必要となります。
3. インストール
本節では、古い PostgreSQL から稼動を継続したままデータ移行する用途での Slony-I インストール例を示します。Linux 上で PostgreSQL 8.3.x を Slony-I 2.2.x を使って PostgreSQL 9.6.x に移行する想定です。以下の図の構成を目指します。
Slony-I は PostgreSQLの公式yumリポジトリにも含まれています。しかしながら、古いバージョンの PostgreSQL と新しいバージョンの PostgreSQL とで、用意されている Slony-I バージョンが異なるため、ここでは Slony-I 公式サイトで配布されているソースコードからビルドします。
$ tar jxf slony1-2.2.5.tar.bz2 $ cd slony1-2.2.5 $ ./configure --prefix=/usr/local/pgsql/slony1-2.2.5 --with-pgconfigdir=/usr/local/pgsql-9.6.1/bin $ make $ sudo make install
8.4.x 以前の場合、PostgreSQL は –enable-thread-safety オプション付きでビルドされている必要があります。ただし、これはクライアントライブラリのみに影響があるオプションですので、稼働中の PostgreSQL 8.x サーバは変更せず、別の PostgreSQL 実行ファイルを用意して対処できます。以下のようにインストール先を示す –with-pgpkglibdir と –with-pgsharedir に別のパスを上書き指定します。
$ ./configure --prefix=/usr/local/pgsql/slony1-2.2.5 --with-pgconfigdir=/usr/local/pgsql-8.3.23-threadsafe/bin --with-pgpkglibdir=/usr/local/pgsql-8.3.23/lib --with-pgsharedir=/usr/local/pgsql-8.3.23/share $ make $ sudo make install
4. レプリケーションの構成
Slony-I の設定と操作をするには slonik コマンドを使います。最初に、繰り返し使うコマンド文字列を環境変数に収めておきます。ここではクラスタ名と両ノードの接続文字列を指定します。なお、slonik コマンドはどちらのホストで実行しても構いません。
$ export PREAMBLE=" cluster name = cl1; node 1 admin conninfo = 'dbname=db1 host=oldhost user=postgres'; node 2 admin conninfo = 'dbname=db1 host=newhost user=postgres'; "
クラスタを初期化するには init cluster 命令を使います。ノード 1 をマスターノードと指定しています。
$ slonik <<EOF ${PREAMBLE} init cluster (id = 1); EOF
続いて、ノード 2 を追加して、パス(ノード間のつながり)を設定します。
$ slonik <<EOF ${PREAMBLE} store node (id = 2, event node = 1); store path (server = 1, client = 2, conninfo = 'dbname=db1 host=oldhost user=postgres'); store path (server = 2, client = 1, conninfo = 'dbname=db1 host=newhost user=postgres'); EOF
以下のメッセージが出ますが問題ありません。9.6.x でも動作します。
<stdin>:6: Possible unsupported PostgreSQL version (90601) 9.6, defaulting to 8.4 support
両サーバでそれぞれ slon プロセスを起動します。各ノードごとに slon プロセスを稼働させます。
レプリケーションを行うテーブルを指定します。まず、セットを定義して、そこにレプリケーションを行うテーブルを加えます。対象テーブルには主キーが必要です。また、宛先データベースに予め同じ定義のテーブルを作っておく必要があります。
$ slonik <<EOF ${PREAMBLE} create set (id = 1, origin = 1, comment = 'set 1'); set add table (id = 1, set id = 1, origin = 1, fully qualified name = 'public.t1'); set add table (id = 2, set id = 1, origin = 1, fully qualified name = 'public.t2'); EOF
レプリケーションを開始します。この後、テーブルの初期コピーが始まり、その後、継続的なデータ同期が行われます。
$ slonik <<EOF ${PREAMBLE} subscribe set (id = 1, provider = 1, receiver = 2); EOF
レプリケーションを中止するには以下を実行します。
$ slonik <<EOF ${PREAMBLE} unsubscribe set (id = 1, receiver = 2); EOF
Slony-I の管理用テーブルや関数を削除するには、slonik コマンドで各々drop、uninstall していくことができます。しかしながら、全てを削除するなら、以下のように _{クラスタ名} のスキーマを削除するのが簡単です。
$ psql -U postgres db1 db1=# DROP SCHEMA _cl1 CASCADE;
全ての操作はデータベース稼動中に実行可能です。ただし、テーブルにトリガを付与したり、外したりするため、slonik コマンド実行時に強いロックが生じることがあります。アプリケーションに長いロック待ちやデッドロックエラーを生じさせないためには、アクセスが少ない時間帯に操作したり、小さい単位で指定を与える等の工夫が必要です。
5. まとめ
本文書では旧バージョン PostgreSQL から停止時間を最小化した移行のために Slony-I を使用する例を紹介しました。Slony-I では、この他に、シーケンスの同期、カスケードでのレプリケーション、スレーブをマスタに切り替え、といったことができます。
Slony-I は比較的古いソフトウェアであるため、情報収集にあたってはどのバージョンについて書かれているか注意してください。バージョンによって slonik に与えるコマンドの必須オプションが違っていたりします。しかしながら、少なくとも 2.x バージョン以降においては基本的な概念に違いはありません。