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から開発中の最新のソースコードにアクセスできます.
cvs -d:pserver:anonymous@cvs.pgfoundry.org:/cvsroot/pgpool loginとすると,パスワードを聞かれるので,何も入力せずにリターンを押す. この操作は最初の1回だけ.これだけでは何もソースは取得されない.
cvs -z3 -d:pserver:anonymous@cvs.pgfoundry.org:/cvsroot/pgpool co pgpoolとする.なお,2回目以降は,pgpoolのソースディレクトリで,
cvs -z3 updateとするだけで最新のソースと同期が取れる.
CVSをHTMLでブラウズする こともできます.
| pgpoolのメリット |
世の中にはpgpool以外にもデータベース用のコネクションプールサーバが 存在しますが,それらと比較した場合のpgpoolのメリットを説明します.
コネクションプール用のソフトには専用の特別なAPI(アプリケーショ ンプログラムインターフェイス)を経由しないと利用できないものもあ りますが,pgpoolはクライアントから見ると普通のPostgreSQLサーバ に見えるため,そのようなAPIを使用する必要がありません.今まで PostgreSQLを使っていたアプリケーションは,接続先のポート番号や ホストを変更するだけですぐにpgpoolが利用できるようになります.
pgpoolはPostgreSQLのクライアントやアプリケーションから見ると普 通のPostgreSQLサーバに見えます.したがってPHP, Perl, Javaなど 各言語用のPostgreSQL用APIがそのまま使えます.
Apacheなどと同様,あらかじめサーバプロセスをforkしておくアーキ テクチャを採用.コネクション要求の度にサーバプロセスをforkする 方式に比べ,オーバヘッドが少なく,応答性が優れています.
pgpoolには「フェイルオーバー」の機能があります.すなわち, PostgreSQLサーバを2台指定しておき,1台がダウンした際に自動的に2 台目のサーバに切り替えることができます.フェイルオーバー機能に より,システムのダウンタイムを最小限に押さえることができます. ただし,2台のPostgreSQLサーバのデータを同期させる機能はありません (pgpool-IIにはオンライン状態のままでデータの同期を取る「オンラインリカバリ」機能があります)
pgpoolは「レプリケーション」も可能です.レプリケーションを使用する ことにより,物理的に2台のディスクにリアルタイムでハードディスクのバッ クアップを取ることができ,片方にディスク障害が発生しても運用を継続する ことができます (pgpoolでは使用できるPostgreSQLサーバは2台までです.pgpool-IIでは3台以上のサーバ利用できます).
レプリケーションモードで動作している場合,pgpoolは「負荷分散」を行うことができます. なお,副作用のあるSELECT文,たとえば更新を伴う関数の呼び出しを行う SELECT文を負荷分散すると,2台のDBサーバの間でデータの不整合が起きます ので,注意してください.この問題は,SELECT文の前に空白やコメントを挿入 して負荷分散させないことによって回避できます.
| pgpoolのデメリット |
PostgreSQLに対するアクセスはすべていったんpgpoolを経由するため, その分のオーバヘッドがあります.
現時点では,以下の機能がサポートされていません.
TCP/IPコネクションを許可している場合(後述の allow_inet_domain_socketが1の場合),pgpool自体にはどのホストか らでも接続できてしまいます.必要ならばiptablesなどを使ってアク セス制限をかけて下さい. (pgpool-IIにはアクセス制限機能があります)
CREATE TEMP TABLEで作成されたテーブルはフロントエンドがセッションを終 了しても削除されません.これは,コネクションプールの効果でバックエンド から見るとセッションが継続しているように見えるからです.セッションの終 了時に明示的にDROP TABLEするか,トランザクションブロックの中でCREATE TEMP TABLE ... ON COMMIT DROPをお使い下さい.reset_query_listを活用す ることもできます.PostgreSQL 8.3以降では,reset_query_listに"DISCARD ALL"と書くことによって この問題が解決できます.
同じ理由でPREPAREで作成されたプランはセッションが終わっても削除されま せん.DEALLOCATEで明示的に削除してください.PostgreSQL 8.3以降では,reset_query_listに"DISCARD ALL"と書くことによって この問題が解決できます.
同じ問い合わせを送っても異なる結果を返すようなデータ,たとえば乱数やト ランザクション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サーバに障害が発生すると,自動的に縮退運転を行います. 例を示します.今,
縮退運転に入ると以後masterとsecondaryのデータは一致しない状態になる可 能性があります.再度レプリケーション運転に入る前に,一旦両系を停止し, rsyncなどを使って手動でデータベースクラスタの状態を一致させてください. (pgpool-IIにはオンライン状態のままでデータの同期を取る「オンラインリカバリ」機能があります) この際,障害の状況によっては必ずしもmaster側が最新とは限らないので注意 してください.master,secondaryのどちらで縮退運転をしているかは, pgpoolにpsqlなどから"show pool_status"コマンドを投げることで確認できま す.
| レプリケーションとデッドロック |
まったく同じ問い合わせを2つのサーバに発行することによってレプリケーショ ンを行うpgpoolでは,単体のPostgreSQLでは発生しないデッドロック状態が起 こり得ます.その理由は,pgpoolでは,問い合わせを
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つの方法を用意しています.| 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には以下のような設定項目があります.
TCP/IPコネクションを受け付けるアドレスをホスト名またはIPアドレスで 指定します.「*」を指定するとすべてのIPインタフェースからのコネクショ ンを受け付けます.「''」を指定するとTCP/IPコネクションを受け付けま せん.デフォルト値は「localhost」です. UNIXドメインソケット経由のコネクションは常に受け付けます. なお,以前のバージョンと互換性を保つため,allow_inet_domain_socket ディレクティブを使用することもできます. allow_inet_domain_socket = 1 は, listen_addresses = '*' と同じで, allow_inet_domain_socket = 0 は listen_addresses = '' と同じです.
pgpoolがコネクションを受け付けるポート番号です.デフォルト値は9999 です.
pgpoolがコネクションを受け付けるUnix domain socketディレクトリです. デフォルト値は'/tmp'です.
pgpoolが接続するPostgreSQLサーバ(postmaster)が動いているホストの名 前(文字列)です.デフォルト値は''で,この場合UNIXドメインソケットを 通じて接続を行います.''以外ならばホスト名と見なし,INETドメインソ ケット経由で接続します.この場合,PostgreSQL側ではTCP/IPコネクショ ンを受け付けるようになっていること,またpg_hba.confが適切に設定され ていてpgpoolからの接続を許可するようになっている必要があります (PostgreSQLから見ると,pgpoolはクライアントに見えることを思い出し てください.).
PostgreSQLサーバのポート番号です.デフォルト値は5432です.
PostgreSQLサーバのUnix domain socketのディレクトリです.デフォルト値は'/tmp'です.
フェイルオーバー機能を利用する場合,2台目のPostgreSQLサーバのホスト 名を指定します.デフォルト値は''です.
フェイルオーバー機能を利用する場合,2台目のPostgreSQLサーバのポート 番号を指定します.0を指定するとフェイルオーバしません.デフォルト値 は0です.
preforkするpgpoolのサーバプロセスの数です.デフォルト値は16になっています.
pgpoolの各サーバプロセスがキープするPostgreSQLへの最大コネクション 数です.pgpoolは,ユーザ名,データベースが同じならばコネクションを 再利用しますが,そうでなければ新たにPostgreSQLへのコネクションを確 立しようとします.したがって,ここでは想定される[ユーザ名:データベー ス名]のペアの種類の数だけをmax_poolに指定しておいたよいでしょう.も しそれを超えて新しいコネクションが張られる場合は,一番古いコネクショ ンを削除して新しいコネクションを作ります. max_poolのデフォルト値は4です.
なお,pgpool全体としては,num_init_children*max_pool 分だけ PostgreSQLへのコネクションが張られる点に注意してください.
pgpoolのpreforkされた子プロセスがchild_life_time秒アイドル状態になったときに強制 的にこのプロセスを終了し,新しいプロセスを起動し直します.0を指定する と強制終了を行いません.なお,この機能はまだ実装されていません.
コネクションプール中のコネクションの有効期間を秒単位で指定します.0 を指定すると有効期間は無限になります.connection_life_timeのデフォ ルト値は0です.
各pgpool子プロセスへの接続回数がこの設定値を超えると、その子プロセ スを終了します。child_life_timeやconnection_life_timeが効かないくら い忙しいサーバで、PostgreSQLバックエンドが肥大化するのを防ぐのに有 効です。
pgpoolの各種ログファイルを格納するディレクトリです.現在のところ, pgpool.pidというプロセスIDを格納するファイルだけが作られるようになっ ています.logdirのデフォルト値は'/tmp'です.
レプリケーションモードで動作させる場合はtrueを指定してください.デ フォルト値はfalseです.
このオプションをtrueにすると,masterの問い合わせ処理の完了を待って からsecondaryの処理に移ります.デッドロックの危険性はなくなりますが, masterとsecondaryの間で問い合わせの並列処理を行わなくなるので性能が 低下する場合もあります.
なお,すべての問い合わせではなくて,SQLのコメントを使って一部の問い 合わせのみstrict動作させることもできます.詳細は1.2を参照してくださ い.
このオプションのデフォルト値はtrueです.
replication_strictがfalseのときにデッドロックを監視するためのタイム アウト時間をミリ秒単位で指定します.デフォルト値は5000,すなわち5秒 です.0を指定するとタイムアウトしなくなります.
trueを指定するとレプリケーションモードの際に,SELECT文をマスタとセ カンダリの間でロードバランスします.デフォルト値はfalseです.
ロードバランスモードの時に,マスタとセカンダリにSELECTを振り分ける 「重み」を定義します.マスタとセカンダリのハードウェア性能に差があ るときに有用です.
重みはweight_masterとweight_secondaryに設定された数値の比率で決定さ れます.たとえば,
weight_master = 0.5 weight_secondary = 0.5や
weight_master = 1 weight_secondary = 1はいずれもマスタとセカンダリの重みが等しくなります(デフォルトです).
weight_master = 1 weight_secondary = 0.5ならマスタの方にはセカンダリの2倍の確率でSELECTが割り振られます.
weight_master = 1 weight_secondary = 0
という設定も可能で,この場合はマスタだけにSELECTが割り振られるよう になります.もちろん,INSERTなどの更新系の問い合わせはマスタとセカ ンダリの両方に常に投げられます.
trueを指定するとマスタとセカンダリの間でデータの不一致があった場合 に強制的に縮退運転に入ります.このオプションがfalseの場合は,該当の 問い合わせを強制的に終了するだけに留めます.デフォルト値はfalseです.
セッションが終了するときにコネクションを初期化するためのSQLコマンド を「;」で区切って列挙します.デフォルトは以下のようになっていますが, 任意のSQL文を追加しても構いません.
reset_query_list = 'ABORT; RESET ALL; SET SESSION AUTHORIZATION DEFAULT'
PostgreSQLのバージョンによって使用できるSQLコマンドが違うので, PostgreSQL 7.3以前では注意してください.
「ABORT」は,PostgreSQL 7.4以上ではトランザクションブロックの 中にいない場合には発行されません(無視されます).
PostgreSQL 8.3以上では,
reset_query_list = 'DISCARD ALL';とするのがおすすめです.
trueならばpgpoolのログにタイムスタンプを追加します.デフォルトは trueです.
trueならばマスタ/スレーブモードでpgpoolを運転します. 主にSlony-Iと組み合わせてレプリケーションをさせるときに使います. デフォルトはfalseです.このモードはreplication_modeとは両 立しません.
trueならコネクションをキャッシュします.デフォルトはtrueです.
pgpoolはサーバ障害やネットワーク障害を検知するために,定期的にバッ クエンドに接続を試みます.これを「ヘルスチェック」と言います.障害 が検知されると,フェイルオーバや縮退運転を試みます.
この パラメータは,ネットワークケーブルが抜けた際などにヘルスチェッ クが長時間待たされるのを防ぐためのタイムアウト値を秒単位で指定しま す.デフォルトは20秒です.0を指定するとタイムアウト処理をしません.
なお,ヘルスチェックを有効にすると,ヘルスチェックのための余分の接 続が1つ必要になりますので,PostgreSQLのpostgresql.confの設定項目の max_connectionsを少くとも1増やすようにしてください.
ヘルスチェックを行う間隔を秒単位で指定します.0を指定するとヘルス チェックを行いません.デフォルトは0です(つまりヘルスチェックを行い ません).
ヘルスチェックを行うためのPostgreSQLユーザ名です.
trueならば、load balanceの際にSQL文行頭の空白を無視します(全角ス ペースは無視されません)。これは、DBI/DBD:Pgのように、勝手に行頭にホ ワイトスペースを追加するようなAPIを使い、ロードバランスしたいときに 有効です。
| pgpoolの起動方法 |
pgpoolを起動するもっとも簡単な方法は,
$ pgpool
とするだけです.これで/usr/local/etc/pgpool.confを読み込み,その設 定でサーバを起動します.
指定可能なオプションは次の通りです.
| 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 stopfastは"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の作者でもある石井達夫によって書かれました. 著者はこんなことをやっています.