Welcome to pgpool page

Last modified: Thu Mar 20 10:50:48 JST 2008

pgpoolとは

pgpoolは,PostgreSQL 専用の多機能ミドルウェアで,PostgreSQLクライアントとPostgreSQLサーバの間で両者の仲立ちをします. pgpoolを利用することによって,PostgreSQLの性能を高めたり,信頼性を向上することができます.

pgpoolの歴史

pgpoolは石井達夫によって2003年に個人的に開発され,現在ではPgpool Global Development Groupに寄贈されて,オープンソース開発プロジェクトとして維持されています. pgpoolはその後,大幅に機能が強化されたpgpool-IIプロジェクトへと発展しました. 現在では開発者はpgpool-IIに傾注しており,pgpoolは最小限のバグ修正が行われていますが,将来は維持が終了すると思われます. pgpool-IIは機能的にpgpoolの上位互換であり,移行は容易ですので,今から導入される方は pgpool-IIを利用されることをお勧めします.

pgpoolのライセンスとサポート

pgpoolのライセンスはBSDライクなもので,商用も含めてどのような用途にも無償で自由に使用することができます.

サポートは,日本語ならSRA OSS, Inc.日本支社が運営するpgpool日本語メーリングリストをご利用ください.英語でもよければ,pgfoundry.orgが提供するメーリングリストがご利用になれます. 商用サポートが必要な場合は,SRA OSS, Inc.日本支社にお問い合わせください.

ダウンロード

pgpoolは,pgpool開発ページ(pgfoundry)から ダウンロードできます.

また,CVSを使ってpgfoundry.orgから開発中の最新のソースコードにアクセスできます.

  1. cvs -d:pserver:anonymous@cvs.pgfoundry.org:/cvsroot/pgpool login
    
    とすると,パスワードを聞かれるので,何も入力せずにリターンを押す. この操作は最初の1回だけ.これだけでは何もソースは取得されない.
  2. 実際にソースを取得するには,
    cvs -z3 -d:pserver:anonymous@cvs.pgfoundry.org:/cvsroot/pgpool co pgpool
    
    とする.なお,2回目以降は,pgpoolのソースディレクトリで,
    
    cvs -z3 update
    
    とするだけで最新のソースと同期が取れる.

CVSをHTMLでブラウズする こともできます.

pgpoolのメリット

世の中にはpgpool以外にもデータベース用のコネクションプールサーバが 存在しますが,それらと比較した場合のpgpoolのメリットを説明します.

  1. アプリケーションの変更の必要がありません

    コネクションプール用のソフトには専用の特別なAPI(アプリケーショ ンプログラムインターフェイス)を経由しないと利用できないものもあ りますが,pgpoolはクライアントから見ると普通のPostgreSQLサーバ に見えるため,そのようなAPIを使用する必要がありません.今まで PostgreSQLを使っていたアプリケーションは,接続先のポート番号や ホストを変更するだけですぐにpgpoolが利用できるようになります.

  2. どの言語でも使えます

    pgpoolはPostgreSQLのクライアントやアプリケーションから見ると普 通のPostgreSQLサーバに見えます.したがってPHP, Perl, Javaなど 各言語用のPostgreSQL用APIがそのまま使えます.

  3. prefork型アーキテクチャ

    Apacheなどと同様,あらかじめサーバプロセスをforkしておくアーキ テクチャを採用.コネクション要求の度にサーバプロセスをforkする 方式に比べ,オーバヘッドが少なく,応答性が優れています.

  4. PostgreSQLへの接続数の制限が可能

    PHPからPostgreSQLにアクセスする場合,同時接続数がApacheサーバの プロセス数と等しくなるため,PostgreSQLが過負荷になりがちです. pgpoolではPostgreSQLへの接続数はpreforkしたpgpoolのサーバ数に よって制限されるため,PostgreSQLがもっとも効率良く動作する同時 接続数を維持することができます.

  5. フェイルオーバー機能を装備

    pgpoolには「フェイルオーバー」の機能があります.すなわち, PostgreSQLサーバを2台指定しておき,1台がダウンした際に自動的に2 台目のサーバに切り替えることができます.フェイルオーバー機能に より,システムのダウンタイムを最小限に押さえることができます. ただし,2台のPostgreSQLサーバのデータを同期させる機能はありません (pgpool-IIにはオンライン状態のままでデータの同期を取る「オンラインリカバリ」機能があります)

  6. レプリケーション機能を装備

    pgpoolは「レプリケーション」も可能です.レプリケーションを使用する ことにより,物理的に2台のディスクにリアルタイムでハードディスクのバッ クアップを取ることができ,片方にディスク障害が発生しても運用を継続する ことができます (pgpoolでは使用できるPostgreSQLサーバは2台までです.pgpool-IIでは3台以上のサーバ利用できます).

  7. 負荷分散機能を装備

    レプリケーションモードで動作している場合,pgpoolは「負荷分散」を行うことができます. なお,副作用のあるSELECT文,たとえば更新を伴う関数の呼び出しを行う SELECT文を負荷分散すると,2台のDBサーバの間でデータの不整合が起きます ので,注意してください.この問題は,SELECT文の前に空白やコメントを挿入 して負荷分散させないことによって回避できます.

pgpoolのデメリット
  1. オーバヘッドがあります

    PostgreSQLに対するアクセスはすべていったんpgpoolを経由するため, その分のオーバヘッドがあります.

  2. すべてのlibpqプロトコルがサポートされていません

    現時点では,以下の機能がサポートされていません.

  3. pgpool自体にpg_hba.confによるアクセス制限はかかりません

    TCP/IPコネクションを許可している場合(後述の allow_inet_domain_socketが1の場合),pgpool自体にはどのホストか らでも接続できてしまいます.必要ならばiptablesなどを使ってアク セス制限をかけて下さい. (pgpool-IIにはアクセス制限機能があります)

  4. template1, regressionという名前のデータベースはコネクションプールの対象になりません.
  5. 一時テーブルについて

    CREATE TEMP TABLEで作成されたテーブルはフロントエンドがセッションを終 了しても削除されません.これは,コネクションプールの効果でバックエンド から見るとセッションが継続しているように見えるからです.セッションの終 了時に明示的にDROP TABLEするか,トランザクションブロックの中でCREATE TEMP TABLE ... ON COMMIT DROPをお使い下さい.reset_query_listを活用す ることもできます.PostgreSQL 8.3以降では,reset_query_listに"DISCARD ALL"と書くことによって この問題が解決できます.

  6. PREPAREについて

    同じ理由でPREPAREで作成されたプランはセッションが終わっても削除されま せん.DEALLOCATEで明示的に削除してください.PostgreSQL 8.3以降では,reset_query_listに"DISCARD ALL"と書くことによって この問題が解決できます.

  7. レプリケーションについて

    同じ問い合わせを送っても異なる結果を返すようなデータ,たとえば乱数やト ランザクションID,OID,SERIAL,シーケンス,CURRENT_TIMETSTAMPのような ものに関する問い合わせをレプリケーションすることはできません(正確に は,同じ値でレプリケーションされる保証がありません). SERIALやシーケンスに関しては,関連テーブルをロックすることによって回避 することもできます.

pgpoolの稼働環境

pgpoolは,libpqプロトコルのversion 2(PostgreSQL 6.4-7.3.xで採用)お よびversion 3(PostgreSQL 7.4以降で採用)に対応していますが,RESET ALLに対応してない 7.1あるいはそれ以前のバージョンでは pool.hの

   #undef NO_RESET_ALL
   #define NO_RESET_ALL
に変えてください.

対応するOSはLinux/UNIX計であれば特に制限がありません.Windowsでは動作しません.

レプリケーション中の障害対応について

pgpoolはレプリケーション中にDBサーバに障害が発生すると,自動的に縮退運転を行います. 例を示します.今,

の2台でレプリケーションを行っていたとします.
  1. 正常時
    master, secondaryに同一のデータがレプリケーションされる.
  2. masterに障害が発生
    masterを切り離してsecondaryのみで運用を継続
  3. secondaryに障害が発生
    secondaryを切り離してmasterのみで運用を継続
  4. masterとsecondaryのデータ不一致を検出
pgpoolは全部ではありませんが,要所要所でmasterのsecondaryのデータが一 致しているかどうかをチェックしています.たとえば,同じテーブルなのに列 数が異なるようなケースは,異常と見なされます.このような異常が検出され ると,secondaryのみで運用を継続します.

縮退運転に入ると以後masterとsecondaryのデータは一致しない状態になる可 能性があります.再度レプリケーション運転に入る前に,一旦両系を停止し, rsyncなどを使って手動でデータベースクラスタの状態を一致させてください. (pgpool-IIにはオンライン状態のままでデータの同期を取る「オンラインリカバリ」機能があります) この際,障害の状況によっては必ずしもmaster側が最新とは限らないので注意 してください.master,secondaryのどちらで縮退運転をしているかは, pgpoolにpsqlなどから"show pool_status"コマンドを投げることで確認できま す.

レプリケーションとデッドロック

まったく同じ問い合わせを2つのサーバに発行することによってレプリケーショ ンを行うpgpoolでは,単体のPostgreSQLでは発生しないデッドロック状態が起 こり得ます.その理由は,pgpoolでは,問い合わせを

  1. 問い合わせのリクエストを master, secondary の順に投げる
  2. 結果の待ち合わせを master, secondary の順に行う
というように処理するからです.デッドロックの例を示します.ここでは,
   BEGIN;
   LOCK TABLE t1;
   END;
という単純なトランザクションを考えます.以下の図では,begin, endは 省略しています.また,2つのセッションsession 0とsession 1が進行して いるものとします.
	    master		       secondary
   session 0	session 1	session 0   session 1
   ------------------------------------------------------
   lock	
		lock
					     lock
				lock
   ------------------------------------------------------

session1のmasterはsession0のmasterを待ち続けますが,一方secondaryにお いては,session1が先にロックを獲得したため,session0がsession1を待ち続 けています.このようにしてお互いにお互いを待ち続けるデッドロック状態が 発生します.

pgpoolでは,この問題に対処するため,以下の2つの方法を用意しています.
  1. pgpool.confのreplication_strictをtrueにする
    こうすると,常にsecondaryはmasterの問い合わせ処理が終わってから 問い合わせを処理するようになります.デッドロックが発生する恐れは なくなりますが,masterとsecondaryの並列処理ができなくなるため, パフォーマンスが落ちる可能性がありますが,もっとも安全な方法です. pgpoolはデフォルトでこのモードで動作します.
  2. デッドロックが発生する可能性のある問い合わせの先頭に特別なキーワー ド「/*STRICT*/」を入れる
    たとえば上の例で言うと /*STRICT*/ LOCK TABLE t1; とします.こうすると,この問い合わせだけはmasterとsecondaryが並 列処理しなくなるので,デッドロックが発生しません./*STRICT*/が記 入されていない他の問い合わせは並列処理されるので,効率が良くなり ます. なお,PostgreSQLでは,/*から*/まではコメントとして扱われるので, DB処理に影響はありません.
replication_timeoutについて

万が一デッドロックが発生したときに備え,replication_timeoutを設定する ことができます.単位はミリ秒(1/1000秒)です.もしmasterの処理が終わって からsecondaryがreplication_timeout以内に応答を返さない場合は,該当セッ ションを強制終了することによってデッドロック状態を解消します.

なお,masterに比べ,secondaryの性能が著しく劣る場合にはsecondaryの応答 が遅れ,デッドロックではないのにタイムアウトになることがあります.この 場合は適当にreplication_timeoutを大きくするか,replication_strictを true にします.

注意: replication_strictがtrueの場合にはこのパラメータは無視されま す.

pgpoolのインストール方法

      ./configure
      make
      make install
でインストールが完了します(GNU makeが必要なので,FreeBSDなどでは makeをgmakeに読み替えてください).デフォルトのインストール先は, /usr/local以下で以下のようなファイルがインストールされます.
      /usr/local/bin/pgpool	プログラム本体
      /usr/local/etc/pgpool.conf.sample	設定ファイルサンプル
インストール先を変更する場合は,configure --prefix=path... とし てください.

pgpoolの設定方法

pgpoolの設定パラメータはpgpool.confで設定します.pgpool.conf.sample をpgpool.confにコピーし,設定を行ってください.

pgpool.confの書式は以下です.

pgpool.confには以下のような設定項目があります.

pgpoolの起動方法

pgpoolを起動するもっとも簡単な方法は,

   $ pgpool

とするだけです.これで/usr/local/etc/pgpool.confを読み込み,その設 定でサーバを起動します.

指定可能なオプションは次の通りです.

-f path
デフォルト以外のコンフィギュレーションファイルのパス名を指定します.
-n
デーモンモードで起動しません.このオプションはloggerやrotatelogsな どを使ってエラーメッセージをファイルに出力するときなどに便利です.
-d
デバッグメッセージを大量に出力します.
-h
ヘルプメッセージを出力して終了します.

pgpoolの終了

「stop」オプションを使います.

   $ pgpool [-f path_to_configuration_file][-m {s[mart]|f[ast]|i[mmediate]}] stop
で停止できます.

起動時に-fオプションで設定ファイルをしているときは, stop時にも-fオプションで設定ファイルを指定してください.

まだフロントエンドからの接続が終了していない子プロセスがあると, pgpoolは終了せずにその接続が終了するのを待ちます.stopリクエストが 発行された以後は,新たにクライアントはpgpoolに接続することはできま せん.

待たずに強制的に終了させるには,以下のようにします.

   $ pgpool -m fast stop
   
または
   $ pgpool -m immediate stop
   
fastは"f",immediateは"i"と省略することもできます.ちなみに,
   $ pgpool -m smart stop
   
または
   $ pgpool -m s stop
   
とすると,pgpool stopと同じ動作をします.

スイッチオーバ

メインテナンスなどのために意図的にフェイルオーバや縮退運転モードに 移行することができます.

   $ pgpool [-f config_file] [-s {m[aster]|s[econdary]] switch

-sオプションを省略すると,マスタ側を落とし,セカンダリにフェイルオー バ(コネクションプールモードで動作時)または縮退(レプリケーションモー ドで動作時)します.セカンダリを落としたい場合は,

   $ pgpool [-f config_file] -s s[econdary] switch

とします.

なお,PostgreSQLサーバが1台の状態で動いている場合は,現在のクライア ントからpgpoolへのコネクションを強制的に一度切断し,pgpoolの子プロ セスが再起動されます.

ログの取り方

pgpoolを-nオプション付で起動すると,stderr(標準エラー出力)にエラー や重大な情報(たとえばフェイルオーバしたような場合)に関するメッセー ジが出力されます.このままファイルにリダイレクトすることにより, pgpoolのログを取ることができます.

[実行例]

   pgpool -n >& /tmp/pgpool.log &
または
   pgpool -n > /tmp/pgpool.log 2>&1 &

このとき,print_timestampをtrueにしておくと,タイムスタンプがログに 付加されます(print_timestampはデフォルトでtrueです).

また,loggerコマンドを使ってsyslogにメッセージを出力するのもよい方 法です.

[実行例]

   pgpool -n 2>&1 |logger -t pgpool -p local0.info&
   これにより,以下のようなメッセージがsyslogに出力されます.
   Apr 13 15:07:11 srapc1977  4月 13 15:07:11 pgpool: log: pid 2038: starting failover from (5432) to (5433)
   Apr 13 15:07:11 srapc1977  4月 13 15:07:11 pgpool: log: pid 2038: failover from (5432) to (5433) done.
このページの作者について

pgpoolの作者でもある石井達夫によって書かれました. 著者はこんなことをやっています.