「FAQ」の版間の差分
細 (Adjust style.) |
|||
(4人の利用者による、間の96版が非表示) | |||
1行目: | 1行目: | ||
− | + | __FORCETOC__ | |
− | + | == Pgpool-II FAQ == | |
− | |||
− | + | === '''私の Ubuntu box では "pg_config not found" と設定に失敗するのはなぜですか?''' === | |
− | : | + | : pg_config は libpq-dev パッケージに含まれています。設定の前に libpq-dev パッケージをインストールする必要があります。 |
− | + | === '''プライマリノードにインサートしたレコードがスタンバイノードで表示されないのはなぜですか?''' === | |
− | : | + | : ストリーミングレプリケーションと、テーブルにハッシュインデックスを使っていませんか?それらはストリーミングレプリケーションの制限として知られています。インサートされたレコードはそこにあります。しかし、ハッシュインデックスを使ってそのレコードを参照すると、表示されません。ハッシュインデックスの変更は WAL レコードを作成しないので、スタンバイノードに反映されません。解決方法は、 1) 代わりに btree インデックスを使うか、 2) pgpool-II のレプリケーションモードを使うかです。 |
− | + | === '''pgpool-II のバックエンドサーバとしてバージョンの異なる PostgreSQL を混在させることはできますか?''' === | |
− | : | + | : メジャーバージョンの異なる PostgreSQL(たとえば、8.4.x と 9.0.x)を混在させることはできませんが、 マイナーバージョンの異なる PostgreSQL(たとえば 9.0.3 と 9.0.4)を混在させることはできます。Pgpool-II は PostgreSQL から pgpool-II へ送信されるメッセージは常に同一であることを想定しています。メジャーバージョンが異なる PostgreSQL は異なるメッセージを送信する可能性があり、これは pgpool-II に問題を引き起こす可能性があります。 |
− | + | === '''たとえば、Linux と Windows といったように、pgpool-II のバックエンドサーバとして PostgreSQL のプラットフォームを混在させることはできますか?''' === | |
− | : | + | : ストリーミングレプリケーションモードの場合は、できません。ストリーミングレプリケーションは、プライマリとスタンバイのプラットフォームが物理的に同一である必要があるからです。その一方で、pgpool-II の レプリケーションモードは論理的にデータベースクラスタが同一であることしか必要でありません。しかしながら、 オンラインリカバリのスクリプトは rsync やデータベースクラスタを含めた物理的なコピーといったようなことに使えない点に注意してください。代わりに pg_dumall を使ってください。 |
− | : | + | === '''pgpool-II がロードバランスを行っていないようですが、なぜですか?''' === |
+ | : まずはじめに、 pgpool-II のロードバランスは "セッションベース" であり "ステートメントベース" ではありません。これはつまり、 ロードバランス用の DB ノードの選択は、セッションの開始時に決定されることを意味しています。したがって、全ての SQL ステートメントは、セッションが終了するまで、同じ DB ノードに送信されます。 | ||
− | : | + | : 他の注意点は、ステートメントが明示的なトランザクションであるかそうでないかということです。ステートメントがトランザクション内であった場合、レプリケーションモードのステートメントはロードバランスされないでしょう。 pgpool-II 3.0 かそれ以降であれば、マスタースレーブモード時の SELECT 文はトランザクション内であってもロードバランスされるでしょう。 |
− | + | : DB ノードの選択方法は LRU といったような方式ではないことに留意してください。Pgpool-II は、pgpool.conf の "weight" パラメータによって無作為に DB ノードを選択します。これはつまり、選択された DB ノードは短期的には他の DB ノードに一様に分散されないことを意味しています。 100 クエリが送信されたあとで、ロードバランスの効果を検査してください。 | |
− | : | + | |
+ | : レプリケーションモードでは、カーソル宣言もロードバランスされません。つまり、レプリケーションモードでは、 "DECLARE..FETCH" は全ての DB ノードに送信されます。これは、SELECT 文には "FOR UPDATE/FOR SHARE" が付属する場合があるからです。psql を含んでいるいくつかのアプリケーションは SELECT 文でカーソルが使えるということに留意してください。例えば、PostgreSQL 8.2からは、"\set FETCH_COUNT n" が実行された場合、psql は無条件に "_psql_cursor" と名付けられたカーソルを使用します。 | ||
+ | |||
+ | === '''ロードバランスの効果を確認するにはどうすればよいですか?''' === | ||
+ | : pgpool.conf の "log_per_node_statement" ディレクティブを有効にしてください。以下はログの一例です: | ||
: <pre>2011-05-07 08:42:42 LOG: pid 22382: DB node id: 1 backend pid: 22409 statement: SELECT abalance FROM pgbench_accounts WHERE aid = 62797;</pre> | : <pre>2011-05-07 08:42:42 LOG: pid 22382: DB node id: 1 backend pid: 22409 statement: SELECT abalance FROM pgbench_accounts WHERE aid = 62797;</pre> | ||
− | : | + | : "DB node id: 1" はどの DB ノードがこのロードバランシングセッションで選択されたかを示しています。 |
− | : | + | : pgpool-II のログを取得したい場合は、必ず pgpool-II に "-n" オプションを指定して起動してください(あるいは、pgpool-II 3.1 かそれ以降であれば、syslog を使うこともできます)。 |
− | + | === '''pgpool の ログで "ProcessFrontendResponse: failed to read kind from frontend. frontend abnormally exited" を受け取るのはなぜですか?''' === | |
− | : | + | : ええと、おそらくクライアントが行儀の悪い振る舞いをしているのでしょう:-) PostgreSQL のプロトコルは、クライアントが接続を終了する際に特定のパケットを送信することを要求します。pgpool-II は クライアントがパケットを送信せずに切断したことを訴えています。これは psql を使って再現可能です。psql で pgpool に接続してください。Kill -9 で psql を終了してください。似たようなログが出力されるでしょう。このメッセージは、正常に psql を終了した場合は表示されないでしょう。その他の可能性はクライアントマシーンと pgpool-II 間の不安定なネットワーク接続です。ケーブルと NIC を確認してみてください。 |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | === '''ストリーミングレプリケーションモードで pgpool-II を実行しています。動作しているようですが、以下のエラーがログにありました。なぜですか?''' === | |
<dl><dd><pre>2011-07-19 08:21:59 ERROR: pid 10727: s_do_auth: unknown response "E" before processing BackendKeyData | <dl><dd><pre>2011-07-19 08:21:59 ERROR: pid 10727: s_do_auth: unknown response "E" before processing BackendKeyData | ||
2011-07-19 08:21:59 ERROR: pid 10727: s_do_auth: unknown response "" before processing BackendKeyData | 2011-07-19 08:21:59 ERROR: pid 10727: s_do_auth: unknown response "" before processing BackendKeyData | ||
49行目: | 43行目: | ||
2011-07-19 08:21:59 ERROR: pid 10727: make_persistent_db_connection: s_do_auth failed | 2011-07-19 08:21:59 ERROR: pid 10727: make_persistent_db_connection: s_do_auth failed | ||
2011-07-19 08:21:59 ERROR: pid 10727: find_primary_node: make_persistent_connection failed</pre></dl> | 2011-07-19 08:21:59 ERROR: pid 10727: find_primary_node: make_persistent_connection failed</pre></dl> | ||
− | : pgpool-II tries to connect to PostgreSQL | + | : pgpool-II は PostgreSQL に接続して pg_current_xlog_location() などの関数を実行します。これらはプライマリサーバの検出やレプリケーションの遅延を確認するために使われます。上記のメッセージは user と health_check_user が同一で、password と health_check_password が同一の状態で pgpool-II が接続に失敗したことを示しています。health_check_period が 0 であったとしても、これらのパラメータは適切に設定してください。 |
+ | |||
+ | : pgpool-II 3.1 かそれ以降であれば sr_check_user と sr_check_password が代わりに使えることを留意してください。 | ||
+ | |||
+ | === '''pgpool-II の検証のために pgbench を実行したら、pgbench がハングしました。PostgreSQL に対して直接 pgbench を実行したらうまくいきました。なぜですか?''' === | ||
+ | : pgbench は実際のトランザクションを実行する前に同時接続("-c" オプションで指定される接続数)を行います。したがって、"-c" で指定された同時接続数が num_init_children を超えた場合、pgbench は pgpool の接続許可を永久に待ち続けるために固まってしまうでしょう(pgpool-II は最大 num_init_children までの同時セッションを受け付けることを忘れないでください。同時セッション数が num_init_children に到達した場合、新しいセッションがキューされます)。その一方で、PostgreSQL は同時セッションを max_connections 以上受け付けません。したがって、この場合は接続をブロックするよりも、PostgreSQL のログを確認してみてください。pgpool-II の接続要求のキューイングを検証したい場合は、pgbench の代わりに psql が使えます。以下の例では、 num_init_children = 1 としています(これは実際には推奨される設定ではありません。単純化しています)。 | ||
+ | <dl><dd><pre>$ psql test <-- connect to pgpool from terminal #1 | ||
+ | psql (9.1.1) | ||
+ | Type "help" for help. | ||
+ | test=# | ||
+ | $ psql test <-- tries to connect to pgpool from terminal #2 but it is blocked. | ||
+ | test=# SELECT 1; <--- do something from terminal #1 psql | ||
+ | test=# \q <-- quit psql session on terminal #1 | ||
+ | psql (9.1.1) <-- now psql on terminal #2 accepts session | ||
+ | Type "help" for help. | ||
+ | test=# </pre></dl> | ||
+ | |||
+ | === '''pgpool-II を通して md5 認証ができるように pool_hba.conf と pool_passwd を設定しましたが、 うまく動作しません。なぜですか?''' === | ||
+ | : おそらく、どこかを間違えています。参考として pg_hba.conf、pool_hba.conf、pool_passwd 設定時のエラーパターンを表にしておきます。 | ||
+ | <dl><dd> | ||
+ | {|styles="background:white; color:black" border="1" | ||
+ | |- | ||
+ | |pg_hba.conf | ||
+ | |pool_hba.conf | ||
+ | |pool_passwd | ||
+ | |result | ||
+ | |- | ||
+ | |md5 | ||
+ | |md5 | ||
+ | |yes | ||
+ | |md5 auth | ||
+ | |- | ||
+ | |md5 | ||
+ | |md5 | ||
+ | |no | ||
+ | |"MD5" authentication with pgpool failed for user "XX" | ||
+ | |- | ||
+ | |md5 | ||
+ | |trust | ||
+ | |yes/no | ||
+ | |MD5 authentication is unsupported in replication, master-slave and parallel mode | ||
+ | |- | ||
+ | |trust | ||
+ | |md5 | ||
+ | |yes | ||
+ | |no auth | ||
+ | |- | ||
+ | |trust | ||
+ | |md5 | ||
+ | |no | ||
+ | |"MD5" authentication with pgpool failed for user "XX" | ||
+ | |- | ||
+ | |trust | ||
+ | |trust | ||
+ | |yes/no | ||
+ | |no auth | ||
+ | |} | ||
+ | </dl> | ||
+ | |||
+ | === '''pgpool-II の SSL 設定はどうすればよいですか?''' === | ||
+ | : pgpool-II の SSL サポートは 2 つのパートからなっています: 1) クライアントと pgpool-II 間、 2) pgpool-II と PostgreSQL 間です。#1 と #2 は互いに独立しています。たとえば、#1 か #2 のどちらかだけ SSL 接続を有効にできます。あるいは、#1 と #2 のどちらも有効にできます。#1 について説明します(#2 については、PostgreSQL のドキュメントを確認してください)。 | ||
+ | |||
+ | : pgpool が openssl を有効にした状態でビルドされていることを確認してください。ソースコードからビルドする場合、--with-openssl オプションを使ってください。 | ||
+ | |||
+ | : はじめにサーバ証明証を作成します。以下のコマンドで、PEM パスフレーズ(pgpool 起動時に要求されます)を要求されます。 | ||
+ | : パスフレーズの要求なしに pgpool を起動したい場合は、あとで削除することも可能です([[sample server certficate create session]])。 | ||
+ | <dl><dd><pre>openssl req -new -text -out server.req</pre></dl> | ||
+ | : 必要であれば、 PEM パスフレーズを削除してください。 | ||
+ | <dl><dd><pre>$ openssl rsa -in privkey.pem -out server.key | ||
+ | Enter pass phrase for privkey.pem: | ||
+ | writing RSA key | ||
+ | $ rm privkey.pem</pre></dl> | ||
+ | : 証明書を自己署名証明書に変更してください。 | ||
+ | <dl><dd><pre>$ openssl req -x509 -in server.req -text -key server.key -out server.crt</pre></dl> | ||
+ | : server.key と server.crt を適切な場所にコピーしてください。ここでは /usr/local/etc にコピーしたことにします。server.key の適切なパーミッションを維持するために、 cp -p を必ず使ってください。あるいは、パーミッションを後で設定してください。 | ||
+ | <dl><dd><pre>$ chmod og-rwx /usr/local/etc/server.key</pre></dl> | ||
+ | : 証明書と鍵の位置を pgpool.conf で設定してください。 | ||
+ | <dl><dd><pre>ssl = on | ||
+ | ssl_key = '/usr/local/etc/server.key' | ||
+ | ssl_cert = '/usr/local/etc/server.crt'</pre></dl> | ||
+ | : pgpool を再起動してください。クライアントと pgpool 間の SSL 接続が動作しているか確認するために psql で pgpool に接続してください。 | ||
+ | <dl><dd><pre>psql -h localhost -p 9999 test | ||
+ | psql (9.1.1) | ||
+ | SSL connection (cipher: AES256-SHA, bits: 256) | ||
+ | Type "help" for help. | ||
+ | |||
+ | test=# \q</pre></dl> | ||
+ | : "SSL connection..." と表示されていたら、クライアントと pgpool 間の SSL 接続は動作しています。"-h localhost" オプションを必ず使用してください。SSL は TCP/IP でのみ動作し、Unix ドメインソケットでは動作しないからです。 | ||
+ | |||
+ | === '''レプリケーションモードで pgpool-II を使っています。 pgpool-II が INSERT クエリ内の current_timestamp を呼び出し時の同一時刻に置き換えること期待しましたが、置き換えられませんでした。なぜですか?''' === | ||
+ | :おそらく、INSERT クエリが(public.mytable のような)スキーマが修飾されたテーブル名を使っており、 pool_regclass 関数を pgpool にインストールしていないのでしょう。pgpool_reglclass がないと pgpool-II はスキーマ修飾を除いたテーブル名のみを扱います。 | ||
+ | |||
+ | === '''max_connection が not max_connection >= num_init_children でなく、max_connection >= (num_init_children * max_pool) を満たしていなければならないのはなぜですか?''' === | ||
+ | : おそらく、pgpool がこれらの値をどのように使うのかを理解する必要があります。以下は、pgpool の内部処理です。 | ||
+ | <ol> | ||
+ | <li>クライアントからの接続要求を待ちます。 | ||
+ | <li>pgpool 子プロセスがクライアントからの接続要求を受けます。 | ||
+ | <li>最大 max_pool の、接続要求されたデータベースとユーザのペアを保持しているコネクションプールから、pgpool 子プロセスは存在している接続を探します。 | ||
+ | <li>見つかれば、それを再利用します。 | ||
+ | <li>見つからなければ、PostgreSQL への新しい接続を開き、それをコネクションプールへ登録します。コネクションプールに空きスロットがなければ、最も古い接続を終了し、そのスロットを再利用します。 | ||
+ | <li>クライアントがセッションの終了要求を送るまで、クエリ処理を行います。 | ||
+ | <li>クライアントの接続を終了しますが、将来の利用のために PostgreSQL への接続は維持します。 | ||
+ | <li>#1 に戻ります。 | ||
+ | </ol> | ||
+ | |||
+ | === '''コネクションプールキャッシュは pgpool プロセス内で共有していますか?''' === | ||
+ | :いいえ、コネクションプールキャッシュは pgpool のプライベートメモリ内に存在しており、他の pgpool と共有されていません。コネクションキャッシュの管理方法は次の通りです: pgpool プロセス 12345 がデータベース A/ユーザ B のコネクションキャッシュを持っており、プロセス 12346 はデータベース A/ユーザ B のコネクションキャッシュを持っておらず、どちらのプロセスもアイドル状態(この時点ではクライアントが接続していない)と仮定します。クライアントがデータベース A/ユーザ Bで、 プロセス 12345 の pgpool に接続する場合、存在している 12345 のコネクションが再利用されます。その一方で、クライアントが プロセス 12346 の pgpool に接続する場合、12346 は新しい接続を作成する必要があります。12345 か 12346 のどちらが選択されるかを、pgpool はコントロールしていません。しかしながら、長期的には各 pgpool 子プロセスが同等に選択され、各プロセスのコネクションプールは同等に再利用されるでしょう。 | ||
+ | |||
+ | === '''SELECT 文がキャッシュされないのはなぜですか?''' === | ||
+ | :iBatis, MyBatis といったいくつかのライブラリは、明示的にコミットしない場合、常にトランザクションをロールバックします。不整合を起こす可能性があるので、pgpool はロールバックされたトランザクションの SELECT 文の結果は決してキャッシュしません。 | ||
+ | |||
+ | === '''pool_passwd に # コメントや空行は使えますか?''' === | ||
+ | : 答えはシンプルです。使えません(/etc/passwd と同じようなものです)。 | ||
+ | |||
+ | === '''-n オプションを指定せずに pgpool を起動すると MD5 認証が使えません。なぜですか?''' === | ||
+ | : -f オプションで相対パスを指定しなければなりません: i.e. "-f pgpool.conf" もしくは、フルパスを指定しなければなりません: i.e. "-f /usr/local/etc/pgpool.conf"。 pgpool は pgpool.conf パスから(MD5 認証に必要な)pool_passwd のフルパスを設定しようとします。しかしながら、-n オプションを指定せずに pgpool を起動すると、カレントディレクトリが "/" に変わってしまいます。そしてこれは、プロセスのデーモン化に必要です。結果として、 pgpool は "/pool_passwd" を開こうとして失敗してしまいます。 | ||
+ | |||
+ | === '''ストリーミングレプリケーションモード時にスタンバイサーバが故障状態になり、 PostgreSQL の "terminating connection due to conflict" というメッセージを確認しました。なぜですか?''' === | ||
+ | : 以下のメッセージを含んでいるとしたら、プライマリサーバの vacuum がスタンバイサーバの SELECT 文で参照しようとした行を削除してしまった可能性があります。回避方法は、スタンバイサーバのpostgresql.conf に "hot_standby_feedback = on" を設定することです。 | ||
+ | <dl><dd><pre> | ||
+ | 2013-04-07 19:38:10 UTC FATAL: terminating connection due to conflict with recovery | ||
+ | 2013-04-07 19:38:10 UTC DETAIL: User query might have needed to see row versions that must be removed. | ||
+ | 2013-04-07 19:38:10 UTC HINT: In a moment you should be able to reconnect to the database and repeat your command. | ||
+ | 2013-04-07 19:38:10 UTC LOG: could not send data to client: Connection reset by peer | ||
+ | 2013-04-07 19:38:10 UTC ERROR: canceling statement due to conflict with recovery | ||
+ | 2013-04-07 19:38:10 UTC DETAIL: User query might have needed to see row versions that must be removed. | ||
+ | 2013-04-07 19:38:10 UTC LOG: could not send data to client: Broken pipe | ||
+ | 2013-04-07 19:38:10 UTC FATAL: connection to client lost | ||
+ | </pre></dl> | ||
+ | |||
+ | === '''pgpool-II が起動しているシステムのロードアベレージが 5 〜 10 程度に高くなります。なぜですか?''' === | ||
+ | : 多数のユーザが Linux kernel 3.0. 2.6 か 3.2 のみで発生すると述べています。私達は、Linux Kernel 3.0 の問題ではないかと推測しています。 詳細なディスカッションは "[pgpool-general: 1528] Mysterious Load Spikes" を参照してください。 | ||
− | : | + | === '''watchdog を有効にした状態で接続数が num_init_children に到達すると、VIP のスイッチオーバーが発生します。なぜですか?''' === |
+ | :接続数が num_init_children に到達すると、select 1 が失敗するので watchdog が失敗します。そのため、 VIP は他の pgpool へ移動します。残念ながら、通常のクライアントと watchdog の接続を区別する方法はありません。num_init_children と wd_life_point を増やし、ler wd_interval を減らすとこの問題をいくらか防ぐことができるかもしれません。 | ||
+ | |||
+ | :次のメジャーバージョンの pgpool-II 3.3 では、この問題を解決するために 'SELECT 1' のようなクエリの代わりに UDP のハートビートパケットを使った新しい監視方法をサポートします。 | ||
+ | |||
+ | === '''pgpool_regclass をインストールする必要があるのはなぜですか? ''' === | ||
+ | :PostgreSQL 8.0 かそれ以降を使用している場合、pgpool-II がアクセスできるようにするために全ての PostgreSQL に pgpool_regclass 関数をインストールすることは強く推奨されており、実際に pgpool-II は内部でそれを利用しています。 pgpool_regclass 関数がないと、異なるスキーマの同じテーブル名を扱う場合に問題を引き起こす可能性があります(一時テーブルは問題ありません)。 | ||
+ | :関連のある FAQ はこちらです。 https://www.pgpool.net/mediawiki/index.php?title=FAQ&action=submit#I.27m_using_pgpool-II_in_replication_mode._I_expected_that_pgpool-II_replaces_current_timestamp_call_with_time_constants_in_my_INSERT_query.2C_but_actually_it_doesn.27t._Why.3F | ||
+ | :PostgreSQL 9.4、pgpool-II 3.3.4 または pgpool-II 3.4.0 以降を使用している場合は、pgpool_regclassのインストールは必要ありません。PostgreSQLに同等の関数 (to_regclass) が含まれているからです。 | ||
+ | |||
+ | === '''md5 認証が動作しません。助けてください。''' === | ||
+ | : md5 認証セットアップのチェックポイントがとても良くまとめられたサマリがあります。そこを参照してください。 | ||
+ | : https://www.pgpool.net/pipermail/pgpool-general/2013-May/001773.html | ||
+ | |||
+ | === '''Amazon AWS で pgpool/PostgreSQL を運用していると、時々ネットワークエラーになります。なぜですか?''' === | ||
+ | : AWS の既知の問題です。Amazon のサポートを利用することをお勧めします。 | ||
+ | : pgpool-II 3.3.4、3.2.9 以降、この問題は、バックエンドに接続する際のタイムアウト値 (実際には connect()システムコール) を 1秒から 10秒に変更することで防ぐことができました。 | ||
+ | : また、 pgpool-II 3.4 以降、このタイムアウト値をスイッチさせるようになりました。 | ||
+ | |||
+ | === '''私の Ubuntu box では pcp コマンドが実行できません。なぜですか?''' === | ||
+ | : pcp コマンドは libpcp.so を必要とします。Ubuntu では "libpgpool0" パッケージに含まれています。 | ||
+ | |||
+ | === '''オンラインリカバリに失敗しました。どのようにデバッグすればよいですか?''' === | ||
+ | : pcp_recovery_node は recovery_1st_stage_command と recovery_2nd_stage_command の両方かどちらかを実行し、これは設定次第です。これらのスクリプトはマスターの PostgreSQL ノード(レプリケーションモード時の始めの稼働ノードか、ストリーミングレプリケーション時のプライマリノード)で実行されることになっています。"BackendError" は pgpool と PostgreSQL の両方かどちらか一方になにか問題が発生したことを意味します。これを検証するには、以下の手順をお勧めします。 | ||
+ | <ol> | ||
+ | <li>デバッグオプションを指定して pgpool を起動します。 | ||
+ | <li>pcp_recovery_node を実行します。 | ||
+ | <li>pgpool とマスターの PostgreSQL のログを確認します。 | ||
+ | </ol> | ||
+ | |||
+ | === ''' 他のノードが稼働しているのに、Watchdog が起動しません。'''=== | ||
+ | : 仕様です。Watchdog の 生存監視は全ての pgpool の起動が完了した後で開始します。これまでは、 仮想 IP のフェイルオーバが全く発生しませんでした。 | ||
+ | |||
+ | === '''トランザクションを開始すると、pgool-II もスタンバイノードでトランザクションを開始します。なぜですか?'''=== | ||
+ | : これは JDBC ドライバがカーソルを使いたい場合に必要な処置です。Pgpool-II はカーソル宣言を含めて SELECT 文をスタンバイノードへ自動的に割り振ります。残念ながら、カーソル宣言は明示的なトランザクション内で実行される必要があります。 | ||
+ | |||
+ | === '''スキーマが修飾されたテーブル名を使うと、pgpool-II がオンメモリクエリキャッシュを無効にしてくれず、古いデータを受け取ってしまいます。なぜですか?'''=== | ||
+ | : "pgpool_regclass" 関数をインストールしていないのではないでしょうか。この関数がないと、pgpool-II はスキーマ修飾されたテーブル名のスキーマ名を無視し、キャッシュの無効化に失敗します。 | ||
+ | |||
+ | === '''定期的に "read_startup_packet: incorrect packet length" といったエラーメッセージを受け取ります。これは何を意味しているのですか?'''=== | ||
+ | : Zabbix や Nagios を含んだ監視ツールは、定期的にパケットや ping を pgpool の待ち受けポートに送信します。残念ながらこれらのパケットは適切なコンテンツを有しておらず、pgpool はdラーを出してしまいます。このようなパケットを誰が送信しているか不明な場合、"log_connections" を有効にして送信元のホストとポートを確認することができます。送信元が監視ツールであれば、この問題を回避するために監視を停止するか、より良い手段として、監視方法を "SELECT 1" のような適切なクエリに変更してください。 | ||
+ | |||
+ | === '''数分おきに繰り返し Tomcat で "An I/O Error occurred while sending to the backend" といったエラーを受け取ります。なぜですか?'''=== | ||
+ | : Tomcat は pgpool に持続的な接続を作成します。client_idle_limit を有効にしている場合、 pgpool はその接続を終了し、次の機会では Tomcat が pgpool に 何かを送信しようとした際にエラーメッセージを伴って送信内容は破棄されてしまいます。 | ||
+ | : 解決方法は client_idle_limit を無効に設定することです。しかしながら、これは多くの接続のアイドル状態を放置してしまいます。 | ||
+ | : 別の解決方法が、Lachezar Dobrevlution 氏によって提供されました: | ||
+ | <blockquote> | ||
+ | : Tomcat側 に time-out を設定すると解決できるかもしれません。 https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html | ||
+ | : (私が知る限りで)設定するパラメータは以下です。: | ||
+ | : minIdle (default is 10, set to 0) | ||
+ | : timeBetweenEvictionRunsMillis (default 5000) | ||
+ | : minEvictableIdleTimeMillis (default 60000) | ||
+ | : この設定は 5 秒ごとに監視を試み、接続が過去 60 秒間利用されていなければ、いかなる接続も終了します。両者の合計値を pgpool のクライアントのタイムアウト値よりも低くしていれば、pgpool 側のタイムアウトの前に、Tomcat 側で接続が終了するでしょう。 | ||
+ | : 以下の設定もまた有用です。 | ||
+ | : testOnBorrow (default false, set to true) | ||
+ | : validationQuery (default none, set to 'SELECT version();' no quotes) | ||
+ | : これは、アプリケーションに終了した接続を提供することなく、その接続が待機中で終了すべき接続であるかを確認するのに有効でしょう。 | ||
+ | </blockquote> | ||
+ | |||
+ | === '''pg_stat_activityを見ると、"SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.oid = pgpool_regclass('pgbench_accounts') AND c.relpersistence = 'u'"のようなクエリが長い間"active"になっています。 何故でしょう?''' === | ||
+ | :それはpg_stat_activityの制限事項です。無視していただいて構いません。 | ||
+ | : pgpool-IIは、このようなクエリを内部で利用する目的のためにマスタノードに送ります。ユーザのクエリが拡張問い合わせモード(たとえばJDBCドライバを使用しているとき)のときは、このクエリも拡張問い合わせモードで送られます。pg_stat_activityが拡張問い合わせモードのクエリの終了を認識するためには、pgpool-IIは"Sync"というメッセージを送らなければならないのですが、これを送ってしまうとユーザクエリの実行を阻害する(正確には名前なしポータルが閉じられる)という問題が発生します。そこでpgpool-IIは代わりに"Flush"というメッセージを送りますが、pg_stat_activityはクエリの終了と認識してくれません。 | ||
+ | : 面白いことに、log_durationを有効にしてログを調べると、上記のクエリは終わった状態になっています。 | ||
+ | |||
+ | ==='''数分経過後、いつもオンラインリカバリに失敗するのはなぜでしょうか?'''=== | ||
+ | :PostgreSQLのstatement_timeoutがオンラインリカバリプロセスをkillしているのかもしれません。オンラインリカバリプロセスはSQLステートメントとして実行されており、そのプロセスが長い間実行され続けていると、PostgreSQLはSQLにSIGINTシグナルを送り、プロセスを終了します。データベースのサイズによっては、オンラインリカバリプロセスは多くの時間を要します。statement_timeoutを無効にするか、十分に長い時間を設定してください。 | ||
+ | |||
+ | ==='''"SET default_transaction_isolation TO DEFAULT" が失敗するのはなぜですか?'''=== | ||
+ | <dl><dd><pre> | ||
+ | $ psql -h localhost -p 9999 -c 'SET default_transaction_isolation to DEFAULT;' | ||
+ | ERROR: kind mismatch among backends. Possible last query was: "SET default_transaction_isolation to DEFAULT;" kind details are: 0[N: statement: SET default_transaction_isolation to DEFAULT;] 1[C] | ||
+ | HINT: check data consistency among db nodes | ||
+ | ERROR: kind mismatch among backends. Possible last query was: "SET default_transaction_isolation to DEFAULT;" kind details are: 0[N: statement: SET default_transaction_isolation to DEFAULT;] 1[C] | ||
+ | HINT: check data consistency among db nodes | ||
+ | connection to server was lost | ||
+ | |||
+ | </pre></dl> | ||
+ | : pgpool-II は、ノード 0 が "N" を返す(NOTICE メッセージは PostgreSQL から送られてきます)一方で、ノード 1 は(コマンドが終了したことを表す)"C" を返していることを検出しています。 | ||
+ | : pgpool-II はノード 0 と 1 の両方が同一のメッセージを返すことを期待していますが、実際には異なります。そのため、pgpool-II はエラーを投げます。おそらく、特定のログ / メッセージの設定がノード 0 と 1 とで異なっています。 | ||
+ | : client_min_messages か、それに関連するパラメータを確認してください。 | ||
+ | : それらは同一である必要があります。 | ||
+ | |||
+ | ==='''pgpool-II はどうやってプライマリノードを発見していますか?'''=== | ||
+ | : pgpool-II は各 DB ノードに "pg_SELECT pg_is_in_recovery()" を発行します。true が帰ってきた場合、そのノードはスタンバイノードです。DB ノードのうちの 1 つが false を返した場合、そのノードはプライマリノードであり、リカバリが終了しています。 | ||
+ | : プロモート中のノードは SELCT に対して true を返す可能性があるので、プライマリノードが見つからず、"search_primary_node_timeout" が 0 より大きい場合、pgpool-II は 1 秒間休止し、総休止時間が "search_primary_node_timeout" に到達するまで各ノードへの SELECT クエリの発行を続けます。 | ||
+ | |||
+ | ==='''pg_cancel_backend() または pg_terminate_backend() を使っていいでしょうか?'''=== | ||
+ | : pg_cancel_backend()の利用は問題ありません。 | ||
+ | :pg_terminate_backend()は、postmasterのシャットダウンと同じエラーコードを返すため、フェイルオーバーを引き起こします。そのことに注意してください。Pgpool-II 3.6以降では、ある条件の時にはフェイルオーバーを引き起こさないようになっています。詳細は[https://www.pgpool.net/docs/latest/en/html/restrictions.html マニュアル]を見てください。 | ||
+ | : pgpool-IIは複数のPostgreSQLサーバを管理しています。この関数使うには、バックエンドPIDとバックエンドサーバを指定する必要があります。 | ||
+ | : クエリがプライマリサーバで実行されている場合、次のように関数を呼び出すことができます。 | ||
+ | |||
+ | <dl><dd><pre> | ||
+ | /*NO LOAD BALANCE*/ SELECT pg_cancel_backend(pid) | ||
+ | </pre> | ||
+ | </dl> | ||
+ | : SQLコメントは、SELECT をスタンバイノードに送信されないようにするためです。もちろん直接プライマリサーバに対して実行することもできます。 | ||
+ | : クエリがスタンバイサーバで実行されている場合、スタンバイサーバに対して実行する必要があります。 | ||
+ | |||
+ | ==='''フェイルオーバが発生した場合、クライアントが pgpool に接続できなくなるのはなぜですか?'''=== | ||
+ | : pgpool-IIの子プロセスは、それぞれがクライアントからのセッションに1対1で対応しています。フェイルオーバが発生した場合、pgpool の子プロセスはバックエンドがシャットダウンされたことを検知せず、バックエンドからの反応を待ち続ける状態になってしまいます。これは、不正な処理またはセグメンテーションフォルトを引き起こす可能性があります。そのため、フェイルオーバが発生した場合、pgpoolの親プロセスはまず子プロセスを切断します。また、ノードを切り離すにはpcp_detach_nodeでも同様な操作ができます。 | ||
+ | : Pgpool-II 3.6以降では、ある条件のもとではすべてのコネクションがフェイルオーバーの際に必ずしも切断されないようになっています。詳細はマニュアルを見てください。 | ||
+ | |||
+ | ==='''pgpool のログには "LOG: forked new pcp worker ..," と "LOG: PCP process with pid: xxxx exit with SUCCESS." が出力されたのはなぜですか?'''=== | ||
+ | : pgpool-II 3.5 以前は、PCPコマンドを一度1つのみ実行でき、1つのPCPコマンドは1つだけの子プロセスを起動します。子プロセスの寿命は親プロセスと同じです。 | ||
+ | : pgpool-II 3.5 以降、1つのみのPCPコマンドの制約がなくなり、複数の pcp コマンドが同時に実行することができました。すべてのPCPコマンドに対して、PCP子プロセスが生成され、コマンドが実行されたら、プロセスを終了します。そのため、このメッセージはPCPコマンドが実行され、子プロセスが終了したこと、または新しいPCP worker プロセスが起動されるたことを示す正常動作のメッセージです。 | ||
+ | |||
+ | ==='''pgpoo-II はどのように md5認証を行いますか?'''=== | ||
+ | |||
+ | # PostgreSQL、pgpool はそれぞれ pg_authid または pool_password に md5(password+username)を保存します。以後、これを "S" と称します。 | ||
+ | # md5 認証が必要な場合、pgpool はフロントエンドにランダムな値 salt "s0" を送ります。 | ||
+ | # フロントエンドがmd5(S+s0)をpgpool に返します。 | ||
+ | # pgpool がpgpool_passwd から S を抽出し、md5(S+s0) を計算します。#3 と #4が一致する場合、次にステップに進みます。 | ||
+ | # すべてのバックエンドがpgpool に salt を送ります。例えば、バックエンド b1、b2のsalts は s1 と s2。 | ||
+ | # pgpool が pgpool_passwd から S を抽出し、 md5(S+s1)を計算し、バックエンド b1 に送ります。また、pgpool が pgpool_passwd から S を抽出し、 md5(S+s2)を計算し、バックエンド b2 に送ります。 | ||
+ | # b1と b2 が認証に同意すると、md5 認証に成功します。 | ||
+ | |||
+ | === Pgpool-IIはなぜ自動的にデータベースがオンラインになったことを検知しないのですか? === | ||
+ | : 技術的には可能ですが、安全ではない操作だからです。 | ||
+ | : ストリミーングレプリケーション構成を考えてみてください。スタンバイがオンラインになったとしても、そのことはスタンバイが現在のプライマリに接続したことを必ずしも意味しません。違うプライマリに接続したかもしれませんし、そもそもスタンバイではないかもしれません。もしPgpool-IIがそのようなスタンバイを自動的にオンラインとして認識したら、そうしたスタンバイに送られたSELECTはプライマリとは違う結果を返すでしょうし、そうなったらデータベースアプリケーションにとっては災害状況になってしまいます。 | ||
+ | : また、"pgpool reload"はスタンバイノードをオンラインとして認識することに関しては何も関係がないことに注意してください。それは単に設定ファイルを再読み込みするだけです。 | ||
+ | : なお、Pgpool-II 4.1以降では、十分な安全が確認された時に自動的にスタンバイサーバをオンラインにする機能が追加されています。設定パラメータ"auto_failback"を参照してください。 | ||
+ | |||
+ | ==='''idle_in_transaction_session_timeout を有効にした後、Pgpool-II が DB ノードの状態をすべて停止に設定します'''=== | ||
+ | : idle_in_transaction_session_timeout は PostgreSQL 9.6 で導入されました。アイドル状態のトランザクションをキャンセルするためのものです。 | ||
+ | : 残念ながら、タイムアウトが発生した後、PostgreSQL は致命的なエラーを発生させ、fail_over_on_backend_error が on の場合、Pgpool-II でフェイルオーバを発生させます。 | ||
+ | :不要なフェイルオーバを回避するための方法がいくつかあります。 | ||
+ | <ul> | ||
+ | <li> fail_over_on_backend_error を無効にします。これにより、FATAL エラーが発生してもフェイルオーバは発生しなくなりますが、セッションは終了してしまいます。 | ||
+ | <li> connection_life_time、child_life_time および client_idle_limit を idle_in_transaction_session_timeout より小さく設定します。FATAL エラーが発生しても、セッションは終了しなくなります。ただし、FATAL エラーが発生しない場合でも、1 つ以上の項目が指定された条件を満たす場合、コネクションプールは削除され、性能に影響を与える可能性があります。 | ||
+ | </ul> | ||
+ | |||
+ | === '''Pgpool-II によって接続された PostgreSQL バックエンドの状態を知るにはどうすればよいですか?''' === | ||
+ | : pg_stat_activity に表示されるバックエンドの状態は、「show pool_pools」コマンドを使用して調べることができます。「show pool_pools」で表示される列の 1 つ「pool_backendpid」は、対応する PostgreSQL バックエンドプロセスのプロセス ID です。それが分かったら、「pid」列と一致する pg_stat_activiy の出力を調べることができます。 | ||
+ | : これは、PostgreSQL の dblink 拡張機能を使用して自動的に行うことができます。次にクエリの例を示します。 | ||
+ | |||
+ | <dl><dd><pre> | ||
+ | SELECT * FROM dblink('dbname=test host=xxx port=11000 user=t-ishii password=xxx', 'show pool_pools') as t1 (pool_pid int, start_time text, pool_id int, backend_id int, database text, username text, create_time text,majorversion int, minorversion int, pool_counter int, pool_backendpid int, pool_connected int), pg_stat_activity p WHERE p.pid = t1.pool_backendpid; | ||
+ | </pre> | ||
+ | </dl> | ||
+ | |||
+ | : 上記の SQL は、PostgreSQL または Pgpool-II のいずれかで実行できます。dblink の最初の引数は、PostgreSQL ではなく、Pgpool-II に接続するための接続文字列です。 | ||
+ | |||
+ | === '''Pgpool-II の Debian パッケージはどこで入手できますか?''' === | ||
+ | : こちらから Debian パッケージを入手できます: https://apt.postgresql.org/pub/repos/apt/pool/main/p/pgpool2/ | ||
+ | |||
+ | === '''一般ユーザで Pgpool-II を起動する方法 ''' === | ||
+ | : RPM から Pgpool-II をインストールすると、デフォルトの起動ユーザが root ユーザとなります。 | ||
+ | : 一般ユーザでも Pgpool-II を起動することは可能です。しかし、仮想IP を制御するには root 権限が必要となります。そのため、一般ユーザが 仮想 IP の制御ができるように ip, ifconfig, arping に setuid を設定します。 | ||
+ | |||
+ | |||
+ | : 以下は postgres で Pgpool-II を起動するための設定例です。 | ||
+ | <ol> | ||
+ | <li>pgpool.service ファイルを編集し、起動ユーザを postgres ユーザとする | ||
+ | |||
+ | <pre> | ||
+ | # cp /usr/lib/systemd/system/pgpool.service /etc/systemd/system/pgpool.service | ||
+ | |||
+ | # vi /etc/systemd/system/pgpool.service | ||
+ | ... | ||
+ | User=postgres | ||
+ | Group=postgres | ||
+ | ... | ||
+ | </pre> | ||
+ | |||
+ | <li>/var/{lib,run}/pgpool ファイルの所有者を postgres ユーザに変更 | ||
+ | |||
+ | <pre> | ||
+ | # chown postgres:postgres /var/{lib,run}/pgpool | ||
+ | # cp /usr/lib/tmpfiles.d/pgpool-II-pgxx.conf /etc/tmpfiles.d | ||
+ | # vi /etc/tmpfiles.d/pgpool-II-pgxx.conf | ||
+ | === | ||
+ | d /var/run/pgpool 0755 postgres postgres - | ||
+ | === | ||
+ | </pre> | ||
+ | |||
+ | <li>Pgpool-II 設定ファイルの所有者を postgres ユーザに変更 | ||
+ | <pre> | ||
+ | chown -R postgres:postgres /etc/pgpool-II/ | ||
+ | </pre> | ||
+ | <li>ip/ifconfig/arping コマンドを postgres ユーザのホームディレクトリにコピーし、setuid を設定します | ||
+ | <pre> | ||
+ | # mkdir /var/lib/pgsql/sbin | ||
+ | # chown postgres:postgres /var/lib/pgsql/sbin | ||
+ | # chmod 700 /var/lib/pgsql/sbin | ||
+ | # cp /sbin/ifconfig /var/lib/pgsql/sbin | ||
+ | # cp /sbin/arping /var/lib/pgsql/sbin | ||
+ | # cp /sbin/ip /var/lib/pgsql/sbin | ||
+ | # chmod 4755 /var/lib/pgsql/sbin/ip | ||
+ | # chmod 4755 /var/lib/pgsql/sbin/ | ||
+ | # chmod 4755 /var/lib/pgsql/sbin/arping | ||
+ | </pre> | ||
+ | |||
+ | === '''repmgr をPgpool-IIと一緒に使うことはできますか? ''' === | ||
+ | : いいえ、使えません. これらのソフトウェアは、お互いのことを考慮していません。Pgpool-IIを使う時はrepmgerを使用すべきではありません。詳細はこちらを見てください: https://www.pgpool.net/pipermail/pgpool-general/2019-August/006743.html | ||
+ | |||
+ | === '''CentOS6 で Pgpool-II への接続は失敗しました。''' === | ||
+ | : Pgpool-IIはGSSAPI暗号化に対応していませんが、CentOS6ではGSSAPI接続が要求されます。 これにより、CentOS6で接続が失敗します。 | ||
+ | : この問題を回避するために、CentOS6の環境で「export PGGSSENCMODE=disable」で環境変数を設定する必要があります。 | ||
+ | |||
+ | === '''watchdog のマスタが停止してもスタンバイがマスタを引き継ぎません''' === | ||
+ | |||
+ | : watchdog ノードの数が偶数の場合は、4.1 の新機能である enable_consensus_with_half_votes パラメータを on にする必要があります。これが必要な理由は、4.1 のリリースノートで説明されています。 | ||
+ | <q> | ||
+ | これは、偶数(すなわち、2, 4, 6...) watchdogクラスタにおけるクォーラムの存在および多数決の決定における振る舞いを変更します。 奇数のクラスタ(3, 5, 7...)は影響を受けません。 このパラメータがオフ(デフォルトです)の場合、2ノードのwatchdogクラスタは、クォーラムを持つためには2ノードの両方が生存している必要があります。 クォーラムが存在しないと、1) VIPが失われます 2) フェイルオーバスクリプトが実行されません 3) watchdogのマスターが存在しなくなります。 特に#2は、既存のPostgreSQLがダウンしても新しいプライマリが存在しなくなるので、困ったことになるでしょう。 おそらく2ノードのwatchdogクラスタユーザはi、このパラメータをオンにして、今までと同様に振る舞まうようにしたいでしょう。 一方4ノード以上の偶数watchdogクラスタユーザはこのパラメータがオフであることにメリットがあります。 なぜなら、半分のwatchdogノードがダウンしてsplit brainになる可能性を防ぐことができるからです。 | ||
+ | </q> | ||
+ | |||
+ | == pgpoolAdmin FAQ == | ||
+ | |||
+ | === '''pgpoolAdmin の pgpol status と node status にノード情報がありません。なぜですか?''' === | ||
+ | : pgpoolAdmin は PHP の PostgreSQL エクステンション(pg_connect、pg_query など)を使います。おそらくエクステンションが期待通りに動作していません。apache のエラーログを確認してください。以下の FAQ も確認してください。 | ||
+ | |||
+ | === '''PostgreSQL が稼働中であるにもかかわらず、 pgpoolAdmin の node status が "down" ステータスを示しているのはなぜですか?''' === | ||
+ | : pgpoolAdminは PostgreSQL のステータスを ユーザ = "health_check_user"、データベース = template1 と指定して接続することで監視しています。したがって、pgpoolAdmin が指定のユーザとデータベースにパスワードなしで PostgreSQL にアクセスできるようにする必要があります。PostgreSQL のログでこれを検証することができます。health_check_user が存在しないと以下のようなログが確認できます。: | ||
+ | : <pre>20148 2011-07-06 16:41:59 JST FATAL: role "foo" does not exist</pre> | ||
+ | : If the user is protected by password, you will see: | ||
+ | <dl><dd><pre>20220 2011-07-06 16:42:16 JST FATAL: password authentication failed for user "foo" | ||
+ | 20221 2011-07-06 16:42:16 JST LOG: could not receive data from client: Connection reset by peer | ||
+ | 20221 2011-07-06 16:42:16 JST LOG: unexpected EOF within message length word | ||
+ | 20246 2011-07-06 16:42:26 JST LOG: could not receive data from client: Connection reset by peer | ||
+ | 20246 2011-07-06 16:42:26 JST LOG: unexpected EOF within message length word</pre></dl> |
2020年12月1日 (火) 01:41時点における最新版
目次
- 1 Pgpool-II FAQ
- 1.1 私の Ubuntu box では "pg_config not found" と設定に失敗するのはなぜですか?
- 1.2 プライマリノードにインサートしたレコードがスタンバイノードで表示されないのはなぜですか?
- 1.3 pgpool-II のバックエンドサーバとしてバージョンの異なる PostgreSQL を混在させることはできますか?
- 1.4 たとえば、Linux と Windows といったように、pgpool-II のバックエンドサーバとして PostgreSQL のプラットフォームを混在させることはできますか?
- 1.5 pgpool-II がロードバランスを行っていないようですが、なぜですか?
- 1.6 ロードバランスの効果を確認するにはどうすればよいですか?
- 1.7 pgpool の ログで "ProcessFrontendResponse: failed to read kind from frontend. frontend abnormally exited" を受け取るのはなぜですか?
- 1.8 ストリーミングレプリケーションモードで pgpool-II を実行しています。動作しているようですが、以下のエラーがログにありました。なぜですか?
- 1.9 pgpool-II の検証のために pgbench を実行したら、pgbench がハングしました。PostgreSQL に対して直接 pgbench を実行したらうまくいきました。なぜですか?
- 1.10 pgpool-II を通して md5 認証ができるように pool_hba.conf と pool_passwd を設定しましたが、 うまく動作しません。なぜですか?
- 1.11 pgpool-II の SSL 設定はどうすればよいですか?
- 1.12 レプリケーションモードで pgpool-II を使っています。 pgpool-II が INSERT クエリ内の current_timestamp を呼び出し時の同一時刻に置き換えること期待しましたが、置き換えられませんでした。なぜですか?
- 1.13 max_connection が not max_connection >= num_init_children でなく、max_connection >= (num_init_children * max_pool) を満たしていなければならないのはなぜですか?
- 1.14 コネクションプールキャッシュは pgpool プロセス内で共有していますか?
- 1.15 SELECT 文がキャッシュされないのはなぜですか?
- 1.16 pool_passwd に # コメントや空行は使えますか?
- 1.17 -n オプションを指定せずに pgpool を起動すると MD5 認証が使えません。なぜですか?
- 1.18 ストリーミングレプリケーションモード時にスタンバイサーバが故障状態になり、 PostgreSQL の "terminating connection due to conflict" というメッセージを確認しました。なぜですか?
- 1.19 pgpool-II が起動しているシステムのロードアベレージが 5 〜 10 程度に高くなります。なぜですか?
- 1.20 watchdog を有効にした状態で接続数が num_init_children に到達すると、VIP のスイッチオーバーが発生します。なぜですか?
- 1.21 pgpool_regclass をインストールする必要があるのはなぜですか?
- 1.22 md5 認証が動作しません。助けてください。
- 1.23 Amazon AWS で pgpool/PostgreSQL を運用していると、時々ネットワークエラーになります。なぜですか?
- 1.24 私の Ubuntu box では pcp コマンドが実行できません。なぜですか?
- 1.25 オンラインリカバリに失敗しました。どのようにデバッグすればよいですか?
- 1.26 他のノードが稼働しているのに、Watchdog が起動しません。
- 1.27 トランザクションを開始すると、pgool-II もスタンバイノードでトランザクションを開始します。なぜですか?
- 1.28 スキーマが修飾されたテーブル名を使うと、pgpool-II がオンメモリクエリキャッシュを無効にしてくれず、古いデータを受け取ってしまいます。なぜですか?
- 1.29 定期的に "read_startup_packet: incorrect packet length" といったエラーメッセージを受け取ります。これは何を意味しているのですか?
- 1.30 数分おきに繰り返し Tomcat で "An I/O Error occurred while sending to the backend" といったエラーを受け取ります。なぜですか?
- 1.31 pg_stat_activityを見ると、"SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.oid = pgpool_regclass('pgbench_accounts') AND c.relpersistence = 'u'"のようなクエリが長い間"active"になっています。 何故でしょう?
- 1.32 数分経過後、いつもオンラインリカバリに失敗するのはなぜでしょうか?
- 1.33 "SET default_transaction_isolation TO DEFAULT" が失敗するのはなぜですか?
- 1.34 pgpool-II はどうやってプライマリノードを発見していますか?
- 1.35 pg_cancel_backend() または pg_terminate_backend() を使っていいでしょうか?
- 1.36 フェイルオーバが発生した場合、クライアントが pgpool に接続できなくなるのはなぜですか?
- 1.37 pgpool のログには "LOG: forked new pcp worker ..," と "LOG: PCP process with pid: xxxx exit with SUCCESS." が出力されたのはなぜですか?
- 1.38 pgpoo-II はどのように md5認証を行いますか?
- 1.39 Pgpool-IIはなぜ自動的にデータベースがオンラインになったことを検知しないのですか?
- 1.40 idle_in_transaction_session_timeout を有効にした後、Pgpool-II が DB ノードの状態をすべて停止に設定します
- 1.41 Pgpool-II によって接続された PostgreSQL バックエンドの状態を知るにはどうすればよいですか?
- 1.42 Pgpool-II の Debian パッケージはどこで入手できますか?
- 1.43 一般ユーザで Pgpool-II を起動する方法
- 1.44 repmgr をPgpool-IIと一緒に使うことはできますか?
- 1.45 CentOS6 で Pgpool-II への接続は失敗しました。
- 1.46 watchdog のマスタが停止してもスタンバイがマスタを引き継ぎません
- 2 pgpoolAdmin FAQ
Pgpool-II FAQ
私の Ubuntu box では "pg_config not found" と設定に失敗するのはなぜですか?
- pg_config は libpq-dev パッケージに含まれています。設定の前に libpq-dev パッケージをインストールする必要があります。
プライマリノードにインサートしたレコードがスタンバイノードで表示されないのはなぜですか?
- ストリーミングレプリケーションと、テーブルにハッシュインデックスを使っていませんか?それらはストリーミングレプリケーションの制限として知られています。インサートされたレコードはそこにあります。しかし、ハッシュインデックスを使ってそのレコードを参照すると、表示されません。ハッシュインデックスの変更は WAL レコードを作成しないので、スタンバイノードに反映されません。解決方法は、 1) 代わりに btree インデックスを使うか、 2) pgpool-II のレプリケーションモードを使うかです。
pgpool-II のバックエンドサーバとしてバージョンの異なる PostgreSQL を混在させることはできますか?
- メジャーバージョンの異なる PostgreSQL(たとえば、8.4.x と 9.0.x)を混在させることはできませんが、 マイナーバージョンの異なる PostgreSQL(たとえば 9.0.3 と 9.0.4)を混在させることはできます。Pgpool-II は PostgreSQL から pgpool-II へ送信されるメッセージは常に同一であることを想定しています。メジャーバージョンが異なる PostgreSQL は異なるメッセージを送信する可能性があり、これは pgpool-II に問題を引き起こす可能性があります。
たとえば、Linux と Windows といったように、pgpool-II のバックエンドサーバとして PostgreSQL のプラットフォームを混在させることはできますか?
- ストリーミングレプリケーションモードの場合は、できません。ストリーミングレプリケーションは、プライマリとスタンバイのプラットフォームが物理的に同一である必要があるからです。その一方で、pgpool-II の レプリケーションモードは論理的にデータベースクラスタが同一であることしか必要でありません。しかしながら、 オンラインリカバリのスクリプトは rsync やデータベースクラスタを含めた物理的なコピーといったようなことに使えない点に注意してください。代わりに pg_dumall を使ってください。
pgpool-II がロードバランスを行っていないようですが、なぜですか?
- まずはじめに、 pgpool-II のロードバランスは "セッションベース" であり "ステートメントベース" ではありません。これはつまり、 ロードバランス用の DB ノードの選択は、セッションの開始時に決定されることを意味しています。したがって、全ての SQL ステートメントは、セッションが終了するまで、同じ DB ノードに送信されます。
- 他の注意点は、ステートメントが明示的なトランザクションであるかそうでないかということです。ステートメントがトランザクション内であった場合、レプリケーションモードのステートメントはロードバランスされないでしょう。 pgpool-II 3.0 かそれ以降であれば、マスタースレーブモード時の SELECT 文はトランザクション内であってもロードバランスされるでしょう。
- DB ノードの選択方法は LRU といったような方式ではないことに留意してください。Pgpool-II は、pgpool.conf の "weight" パラメータによって無作為に DB ノードを選択します。これはつまり、選択された DB ノードは短期的には他の DB ノードに一様に分散されないことを意味しています。 100 クエリが送信されたあとで、ロードバランスの効果を検査してください。
- レプリケーションモードでは、カーソル宣言もロードバランスされません。つまり、レプリケーションモードでは、 "DECLARE..FETCH" は全ての DB ノードに送信されます。これは、SELECT 文には "FOR UPDATE/FOR SHARE" が付属する場合があるからです。psql を含んでいるいくつかのアプリケーションは SELECT 文でカーソルが使えるということに留意してください。例えば、PostgreSQL 8.2からは、"\set FETCH_COUNT n" が実行された場合、psql は無条件に "_psql_cursor" と名付けられたカーソルを使用します。
ロードバランスの効果を確認するにはどうすればよいですか?
- pgpool.conf の "log_per_node_statement" ディレクティブを有効にしてください。以下はログの一例です:
2011-05-07 08:42:42 LOG: pid 22382: DB node id: 1 backend pid: 22409 statement: SELECT abalance FROM pgbench_accounts WHERE aid = 62797;
- "DB node id: 1" はどの DB ノードがこのロードバランシングセッションで選択されたかを示しています。
- pgpool-II のログを取得したい場合は、必ず pgpool-II に "-n" オプションを指定して起動してください(あるいは、pgpool-II 3.1 かそれ以降であれば、syslog を使うこともできます)。
pgpool の ログで "ProcessFrontendResponse: failed to read kind from frontend. frontend abnormally exited" を受け取るのはなぜですか?
- ええと、おそらくクライアントが行儀の悪い振る舞いをしているのでしょう:-) PostgreSQL のプロトコルは、クライアントが接続を終了する際に特定のパケットを送信することを要求します。pgpool-II は クライアントがパケットを送信せずに切断したことを訴えています。これは psql を使って再現可能です。psql で pgpool に接続してください。Kill -9 で psql を終了してください。似たようなログが出力されるでしょう。このメッセージは、正常に psql を終了した場合は表示されないでしょう。その他の可能性はクライアントマシーンと pgpool-II 間の不安定なネットワーク接続です。ケーブルと NIC を確認してみてください。
ストリーミングレプリケーションモードで pgpool-II を実行しています。動作しているようですが、以下のエラーがログにありました。なぜですか?
2011-07-19 08:21:59 ERROR: pid 10727: s_do_auth: unknown response "E" before processing BackendKeyData 2011-07-19 08:21:59 ERROR: pid 10727: s_do_auth: unknown response "" before processing BackendKeyData 2011-07-19 08:21:59 ERROR: pid 10727: s_do_auth: unknown response "" before processing BackendKeyData 2011-07-19 08:21:59 ERROR: pid 10727: s_do_auth: unknown response "" before processing BackendKeyData 2011-07-19 08:21:59 ERROR: pid 10727: s_do_auth: unknown response "[" before processing BackendKeyData 2011-07-19 08:21:59 ERROR: pid 10727: pool_read2: EOF encountered with backend 2011-07-19 08:21:59 ERROR: pid 10727: make_persistent_db_connection: s_do_auth failed 2011-07-19 08:21:59 ERROR: pid 10727: find_primary_node: make_persistent_connection failed
- pgpool-II は PostgreSQL に接続して pg_current_xlog_location() などの関数を実行します。これらはプライマリサーバの検出やレプリケーションの遅延を確認するために使われます。上記のメッセージは user と health_check_user が同一で、password と health_check_password が同一の状態で pgpool-II が接続に失敗したことを示しています。health_check_period が 0 であったとしても、これらのパラメータは適切に設定してください。
- pgpool-II 3.1 かそれ以降であれば sr_check_user と sr_check_password が代わりに使えることを留意してください。
pgpool-II の検証のために pgbench を実行したら、pgbench がハングしました。PostgreSQL に対して直接 pgbench を実行したらうまくいきました。なぜですか?
- pgbench は実際のトランザクションを実行する前に同時接続("-c" オプションで指定される接続数)を行います。したがって、"-c" で指定された同時接続数が num_init_children を超えた場合、pgbench は pgpool の接続許可を永久に待ち続けるために固まってしまうでしょう(pgpool-II は最大 num_init_children までの同時セッションを受け付けることを忘れないでください。同時セッション数が num_init_children に到達した場合、新しいセッションがキューされます)。その一方で、PostgreSQL は同時セッションを max_connections 以上受け付けません。したがって、この場合は接続をブロックするよりも、PostgreSQL のログを確認してみてください。pgpool-II の接続要求のキューイングを検証したい場合は、pgbench の代わりに psql が使えます。以下の例では、 num_init_children = 1 としています(これは実際には推奨される設定ではありません。単純化しています)。
$ psql test <-- connect to pgpool from terminal #1 psql (9.1.1) Type "help" for help. test=# $ psql test <-- tries to connect to pgpool from terminal #2 but it is blocked. test=# SELECT 1; <--- do something from terminal #1 psql test=# \q <-- quit psql session on terminal #1 psql (9.1.1) <-- now psql on terminal #2 accepts session Type "help" for help. test=#
pgpool-II を通して md5 認証ができるように pool_hba.conf と pool_passwd を設定しましたが、 うまく動作しません。なぜですか?
- おそらく、どこかを間違えています。参考として pg_hba.conf、pool_hba.conf、pool_passwd 設定時のエラーパターンを表にしておきます。
-
pg_hba.conf pool_hba.conf pool_passwd result md5 md5 yes md5 auth md5 md5 no "MD5" authentication with pgpool failed for user "XX" md5 trust yes/no MD5 authentication is unsupported in replication, master-slave and parallel mode trust md5 yes no auth trust md5 no "MD5" authentication with pgpool failed for user "XX" trust trust yes/no no auth
pgpool-II の SSL 設定はどうすればよいですか?
- pgpool-II の SSL サポートは 2 つのパートからなっています: 1) クライアントと pgpool-II 間、 2) pgpool-II と PostgreSQL 間です。#1 と #2 は互いに独立しています。たとえば、#1 か #2 のどちらかだけ SSL 接続を有効にできます。あるいは、#1 と #2 のどちらも有効にできます。#1 について説明します(#2 については、PostgreSQL のドキュメントを確認してください)。
- pgpool が openssl を有効にした状態でビルドされていることを確認してください。ソースコードからビルドする場合、--with-openssl オプションを使ってください。
- はじめにサーバ証明証を作成します。以下のコマンドで、PEM パスフレーズ(pgpool 起動時に要求されます)を要求されます。
- パスフレーズの要求なしに pgpool を起動したい場合は、あとで削除することも可能です(sample server certficate create session)。
openssl req -new -text -out server.req
- 必要であれば、 PEM パスフレーズを削除してください。
$ openssl rsa -in privkey.pem -out server.key Enter pass phrase for privkey.pem: writing RSA key $ rm privkey.pem
- 証明書を自己署名証明書に変更してください。
$ openssl req -x509 -in server.req -text -key server.key -out server.crt
- server.key と server.crt を適切な場所にコピーしてください。ここでは /usr/local/etc にコピーしたことにします。server.key の適切なパーミッションを維持するために、 cp -p を必ず使ってください。あるいは、パーミッションを後で設定してください。
$ chmod og-rwx /usr/local/etc/server.key
- 証明書と鍵の位置を pgpool.conf で設定してください。
ssl = on ssl_key = '/usr/local/etc/server.key' ssl_cert = '/usr/local/etc/server.crt'
- pgpool を再起動してください。クライアントと pgpool 間の SSL 接続が動作しているか確認するために psql で pgpool に接続してください。
psql -h localhost -p 9999 test psql (9.1.1) SSL connection (cipher: AES256-SHA, bits: 256) Type "help" for help. test=# \q
- "SSL connection..." と表示されていたら、クライアントと pgpool 間の SSL 接続は動作しています。"-h localhost" オプションを必ず使用してください。SSL は TCP/IP でのみ動作し、Unix ドメインソケットでは動作しないからです。
レプリケーションモードで pgpool-II を使っています。 pgpool-II が INSERT クエリ内の current_timestamp を呼び出し時の同一時刻に置き換えること期待しましたが、置き換えられませんでした。なぜですか?
- おそらく、INSERT クエリが(public.mytable のような)スキーマが修飾されたテーブル名を使っており、 pool_regclass 関数を pgpool にインストールしていないのでしょう。pgpool_reglclass がないと pgpool-II はスキーマ修飾を除いたテーブル名のみを扱います。
max_connection が not max_connection >= num_init_children でなく、max_connection >= (num_init_children * max_pool) を満たしていなければならないのはなぜですか?
- おそらく、pgpool がこれらの値をどのように使うのかを理解する必要があります。以下は、pgpool の内部処理です。
- クライアントからの接続要求を待ちます。
- pgpool 子プロセスがクライアントからの接続要求を受けます。
- 最大 max_pool の、接続要求されたデータベースとユーザのペアを保持しているコネクションプールから、pgpool 子プロセスは存在している接続を探します。
- 見つかれば、それを再利用します。
- 見つからなければ、PostgreSQL への新しい接続を開き、それをコネクションプールへ登録します。コネクションプールに空きスロットがなければ、最も古い接続を終了し、そのスロットを再利用します。
- クライアントがセッションの終了要求を送るまで、クエリ処理を行います。
- クライアントの接続を終了しますが、将来の利用のために PostgreSQL への接続は維持します。
- #1 に戻ります。
コネクションプールキャッシュは pgpool プロセス内で共有していますか?
- いいえ、コネクションプールキャッシュは pgpool のプライベートメモリ内に存在しており、他の pgpool と共有されていません。コネクションキャッシュの管理方法は次の通りです: pgpool プロセス 12345 がデータベース A/ユーザ B のコネクションキャッシュを持っており、プロセス 12346 はデータベース A/ユーザ B のコネクションキャッシュを持っておらず、どちらのプロセスもアイドル状態(この時点ではクライアントが接続していない)と仮定します。クライアントがデータベース A/ユーザ Bで、 プロセス 12345 の pgpool に接続する場合、存在している 12345 のコネクションが再利用されます。その一方で、クライアントが プロセス 12346 の pgpool に接続する場合、12346 は新しい接続を作成する必要があります。12345 か 12346 のどちらが選択されるかを、pgpool はコントロールしていません。しかしながら、長期的には各 pgpool 子プロセスが同等に選択され、各プロセスのコネクションプールは同等に再利用されるでしょう。
SELECT 文がキャッシュされないのはなぜですか?
- iBatis, MyBatis といったいくつかのライブラリは、明示的にコミットしない場合、常にトランザクションをロールバックします。不整合を起こす可能性があるので、pgpool はロールバックされたトランザクションの SELECT 文の結果は決してキャッシュしません。
pool_passwd に # コメントや空行は使えますか?
- 答えはシンプルです。使えません(/etc/passwd と同じようなものです)。
-n オプションを指定せずに pgpool を起動すると MD5 認証が使えません。なぜですか?
- -f オプションで相対パスを指定しなければなりません: i.e. "-f pgpool.conf" もしくは、フルパスを指定しなければなりません: i.e. "-f /usr/local/etc/pgpool.conf"。 pgpool は pgpool.conf パスから(MD5 認証に必要な)pool_passwd のフルパスを設定しようとします。しかしながら、-n オプションを指定せずに pgpool を起動すると、カレントディレクトリが "/" に変わってしまいます。そしてこれは、プロセスのデーモン化に必要です。結果として、 pgpool は "/pool_passwd" を開こうとして失敗してしまいます。
ストリーミングレプリケーションモード時にスタンバイサーバが故障状態になり、 PostgreSQL の "terminating connection due to conflict" というメッセージを確認しました。なぜですか?
- 以下のメッセージを含んでいるとしたら、プライマリサーバの vacuum がスタンバイサーバの SELECT 文で参照しようとした行を削除してしまった可能性があります。回避方法は、スタンバイサーバのpostgresql.conf に "hot_standby_feedback = on" を設定することです。
2013-04-07 19:38:10 UTC FATAL: terminating connection due to conflict with recovery 2013-04-07 19:38:10 UTC DETAIL: User query might have needed to see row versions that must be removed. 2013-04-07 19:38:10 UTC HINT: In a moment you should be able to reconnect to the database and repeat your command. 2013-04-07 19:38:10 UTC LOG: could not send data to client: Connection reset by peer 2013-04-07 19:38:10 UTC ERROR: canceling statement due to conflict with recovery 2013-04-07 19:38:10 UTC DETAIL: User query might have needed to see row versions that must be removed. 2013-04-07 19:38:10 UTC LOG: could not send data to client: Broken pipe 2013-04-07 19:38:10 UTC FATAL: connection to client lost
pgpool-II が起動しているシステムのロードアベレージが 5 〜 10 程度に高くなります。なぜですか?
- 多数のユーザが Linux kernel 3.0. 2.6 か 3.2 のみで発生すると述べています。私達は、Linux Kernel 3.0 の問題ではないかと推測しています。 詳細なディスカッションは "[pgpool-general: 1528] Mysterious Load Spikes" を参照してください。
watchdog を有効にした状態で接続数が num_init_children に到達すると、VIP のスイッチオーバーが発生します。なぜですか?
- 接続数が num_init_children に到達すると、select 1 が失敗するので watchdog が失敗します。そのため、 VIP は他の pgpool へ移動します。残念ながら、通常のクライアントと watchdog の接続を区別する方法はありません。num_init_children と wd_life_point を増やし、ler wd_interval を減らすとこの問題をいくらか防ぐことができるかもしれません。
- 次のメジャーバージョンの pgpool-II 3.3 では、この問題を解決するために 'SELECT 1' のようなクエリの代わりに UDP のハートビートパケットを使った新しい監視方法をサポートします。
pgpool_regclass をインストールする必要があるのはなぜですか?
- PostgreSQL 8.0 かそれ以降を使用している場合、pgpool-II がアクセスできるようにするために全ての PostgreSQL に pgpool_regclass 関数をインストールすることは強く推奨されており、実際に pgpool-II は内部でそれを利用しています。 pgpool_regclass 関数がないと、異なるスキーマの同じテーブル名を扱う場合に問題を引き起こす可能性があります(一時テーブルは問題ありません)。
- 関連のある FAQ はこちらです。 https://www.pgpool.net/mediawiki/index.php?title=FAQ&action=submit#I.27m_using_pgpool-II_in_replication_mode._I_expected_that_pgpool-II_replaces_current_timestamp_call_with_time_constants_in_my_INSERT_query.2C_but_actually_it_doesn.27t._Why.3F
- PostgreSQL 9.4、pgpool-II 3.3.4 または pgpool-II 3.4.0 以降を使用している場合は、pgpool_regclassのインストールは必要ありません。PostgreSQLに同等の関数 (to_regclass) が含まれているからです。
md5 認証が動作しません。助けてください。
- md5 認証セットアップのチェックポイントがとても良くまとめられたサマリがあります。そこを参照してください。
- https://www.pgpool.net/pipermail/pgpool-general/2013-May/001773.html
Amazon AWS で pgpool/PostgreSQL を運用していると、時々ネットワークエラーになります。なぜですか?
- AWS の既知の問題です。Amazon のサポートを利用することをお勧めします。
- pgpool-II 3.3.4、3.2.9 以降、この問題は、バックエンドに接続する際のタイムアウト値 (実際には connect()システムコール) を 1秒から 10秒に変更することで防ぐことができました。
- また、 pgpool-II 3.4 以降、このタイムアウト値をスイッチさせるようになりました。
私の Ubuntu box では pcp コマンドが実行できません。なぜですか?
- pcp コマンドは libpcp.so を必要とします。Ubuntu では "libpgpool0" パッケージに含まれています。
オンラインリカバリに失敗しました。どのようにデバッグすればよいですか?
- pcp_recovery_node は recovery_1st_stage_command と recovery_2nd_stage_command の両方かどちらかを実行し、これは設定次第です。これらのスクリプトはマスターの PostgreSQL ノード(レプリケーションモード時の始めの稼働ノードか、ストリーミングレプリケーション時のプライマリノード)で実行されることになっています。"BackendError" は pgpool と PostgreSQL の両方かどちらか一方になにか問題が発生したことを意味します。これを検証するには、以下の手順をお勧めします。
- デバッグオプションを指定して pgpool を起動します。
- pcp_recovery_node を実行します。
- pgpool とマスターの PostgreSQL のログを確認します。
他のノードが稼働しているのに、Watchdog が起動しません。
- 仕様です。Watchdog の 生存監視は全ての pgpool の起動が完了した後で開始します。これまでは、 仮想 IP のフェイルオーバが全く発生しませんでした。
トランザクションを開始すると、pgool-II もスタンバイノードでトランザクションを開始します。なぜですか?
- これは JDBC ドライバがカーソルを使いたい場合に必要な処置です。Pgpool-II はカーソル宣言を含めて SELECT 文をスタンバイノードへ自動的に割り振ります。残念ながら、カーソル宣言は明示的なトランザクション内で実行される必要があります。
スキーマが修飾されたテーブル名を使うと、pgpool-II がオンメモリクエリキャッシュを無効にしてくれず、古いデータを受け取ってしまいます。なぜですか?
- "pgpool_regclass" 関数をインストールしていないのではないでしょうか。この関数がないと、pgpool-II はスキーマ修飾されたテーブル名のスキーマ名を無視し、キャッシュの無効化に失敗します。
定期的に "read_startup_packet: incorrect packet length" といったエラーメッセージを受け取ります。これは何を意味しているのですか?
- Zabbix や Nagios を含んだ監視ツールは、定期的にパケットや ping を pgpool の待ち受けポートに送信します。残念ながらこれらのパケットは適切なコンテンツを有しておらず、pgpool はdラーを出してしまいます。このようなパケットを誰が送信しているか不明な場合、"log_connections" を有効にして送信元のホストとポートを確認することができます。送信元が監視ツールであれば、この問題を回避するために監視を停止するか、より良い手段として、監視方法を "SELECT 1" のような適切なクエリに変更してください。
数分おきに繰り返し Tomcat で "An I/O Error occurred while sending to the backend" といったエラーを受け取ります。なぜですか?
- Tomcat は pgpool に持続的な接続を作成します。client_idle_limit を有効にしている場合、 pgpool はその接続を終了し、次の機会では Tomcat が pgpool に 何かを送信しようとした際にエラーメッセージを伴って送信内容は破棄されてしまいます。
- 解決方法は client_idle_limit を無効に設定することです。しかしながら、これは多くの接続のアイドル状態を放置してしまいます。
- 別の解決方法が、Lachezar Dobrevlution 氏によって提供されました:
- Tomcat側 に time-out を設定すると解決できるかもしれません。 https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html
- (私が知る限りで)設定するパラメータは以下です。:
- minIdle (default is 10, set to 0)
- timeBetweenEvictionRunsMillis (default 5000)
- minEvictableIdleTimeMillis (default 60000)
- この設定は 5 秒ごとに監視を試み、接続が過去 60 秒間利用されていなければ、いかなる接続も終了します。両者の合計値を pgpool のクライアントのタイムアウト値よりも低くしていれば、pgpool 側のタイムアウトの前に、Tomcat 側で接続が終了するでしょう。
- 以下の設定もまた有用です。
- testOnBorrow (default false, set to true)
- validationQuery (default none, set to 'SELECT version();' no quotes)
- これは、アプリケーションに終了した接続を提供することなく、その接続が待機中で終了すべき接続であるかを確認するのに有効でしょう。
pg_stat_activityを見ると、"SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.oid = pgpool_regclass('pgbench_accounts') AND c.relpersistence = 'u'"のようなクエリが長い間"active"になっています。 何故でしょう?
- それはpg_stat_activityの制限事項です。無視していただいて構いません。
- pgpool-IIは、このようなクエリを内部で利用する目的のためにマスタノードに送ります。ユーザのクエリが拡張問い合わせモード(たとえばJDBCドライバを使用しているとき)のときは、このクエリも拡張問い合わせモードで送られます。pg_stat_activityが拡張問い合わせモードのクエリの終了を認識するためには、pgpool-IIは"Sync"というメッセージを送らなければならないのですが、これを送ってしまうとユーザクエリの実行を阻害する(正確には名前なしポータルが閉じられる)という問題が発生します。そこでpgpool-IIは代わりに"Flush"というメッセージを送りますが、pg_stat_activityはクエリの終了と認識してくれません。
- 面白いことに、log_durationを有効にしてログを調べると、上記のクエリは終わった状態になっています。
数分経過後、いつもオンラインリカバリに失敗するのはなぜでしょうか?
- PostgreSQLのstatement_timeoutがオンラインリカバリプロセスをkillしているのかもしれません。オンラインリカバリプロセスはSQLステートメントとして実行されており、そのプロセスが長い間実行され続けていると、PostgreSQLはSQLにSIGINTシグナルを送り、プロセスを終了します。データベースのサイズによっては、オンラインリカバリプロセスは多くの時間を要します。statement_timeoutを無効にするか、十分に長い時間を設定してください。
"SET default_transaction_isolation TO DEFAULT" が失敗するのはなぜですか?
$ psql -h localhost -p 9999 -c 'SET default_transaction_isolation to DEFAULT;' ERROR: kind mismatch among backends. Possible last query was: "SET default_transaction_isolation to DEFAULT;" kind details are: 0[N: statement: SET default_transaction_isolation to DEFAULT;] 1[C] HINT: check data consistency among db nodes ERROR: kind mismatch among backends. Possible last query was: "SET default_transaction_isolation to DEFAULT;" kind details are: 0[N: statement: SET default_transaction_isolation to DEFAULT;] 1[C] HINT: check data consistency among db nodes connection to server was lost
- pgpool-II は、ノード 0 が "N" を返す(NOTICE メッセージは PostgreSQL から送られてきます)一方で、ノード 1 は(コマンドが終了したことを表す)"C" を返していることを検出しています。
- pgpool-II はノード 0 と 1 の両方が同一のメッセージを返すことを期待していますが、実際には異なります。そのため、pgpool-II はエラーを投げます。おそらく、特定のログ / メッセージの設定がノード 0 と 1 とで異なっています。
- client_min_messages か、それに関連するパラメータを確認してください。
- それらは同一である必要があります。
pgpool-II はどうやってプライマリノードを発見していますか?
- pgpool-II は各 DB ノードに "pg_SELECT pg_is_in_recovery()" を発行します。true が帰ってきた場合、そのノードはスタンバイノードです。DB ノードのうちの 1 つが false を返した場合、そのノードはプライマリノードであり、リカバリが終了しています。
- プロモート中のノードは SELCT に対して true を返す可能性があるので、プライマリノードが見つからず、"search_primary_node_timeout" が 0 より大きい場合、pgpool-II は 1 秒間休止し、総休止時間が "search_primary_node_timeout" に到達するまで各ノードへの SELECT クエリの発行を続けます。
pg_cancel_backend() または pg_terminate_backend() を使っていいでしょうか?
- pg_cancel_backend()の利用は問題ありません。
- pg_terminate_backend()は、postmasterのシャットダウンと同じエラーコードを返すため、フェイルオーバーを引き起こします。そのことに注意してください。Pgpool-II 3.6以降では、ある条件の時にはフェイルオーバーを引き起こさないようになっています。詳細はマニュアルを見てください。
- pgpool-IIは複数のPostgreSQLサーバを管理しています。この関数使うには、バックエンドPIDとバックエンドサーバを指定する必要があります。
- クエリがプライマリサーバで実行されている場合、次のように関数を呼び出すことができます。
/*NO LOAD BALANCE*/ SELECT pg_cancel_backend(pid)
- SQLコメントは、SELECT をスタンバイノードに送信されないようにするためです。もちろん直接プライマリサーバに対して実行することもできます。
- クエリがスタンバイサーバで実行されている場合、スタンバイサーバに対して実行する必要があります。
フェイルオーバが発生した場合、クライアントが pgpool に接続できなくなるのはなぜですか?
- pgpool-IIの子プロセスは、それぞれがクライアントからのセッションに1対1で対応しています。フェイルオーバが発生した場合、pgpool の子プロセスはバックエンドがシャットダウンされたことを検知せず、バックエンドからの反応を待ち続ける状態になってしまいます。これは、不正な処理またはセグメンテーションフォルトを引き起こす可能性があります。そのため、フェイルオーバが発生した場合、pgpoolの親プロセスはまず子プロセスを切断します。また、ノードを切り離すにはpcp_detach_nodeでも同様な操作ができます。
- Pgpool-II 3.6以降では、ある条件のもとではすべてのコネクションがフェイルオーバーの際に必ずしも切断されないようになっています。詳細はマニュアルを見てください。
pgpool のログには "LOG: forked new pcp worker ..," と "LOG: PCP process with pid: xxxx exit with SUCCESS." が出力されたのはなぜですか?
- pgpool-II 3.5 以前は、PCPコマンドを一度1つのみ実行でき、1つのPCPコマンドは1つだけの子プロセスを起動します。子プロセスの寿命は親プロセスと同じです。
- pgpool-II 3.5 以降、1つのみのPCPコマンドの制約がなくなり、複数の pcp コマンドが同時に実行することができました。すべてのPCPコマンドに対して、PCP子プロセスが生成され、コマンドが実行されたら、プロセスを終了します。そのため、このメッセージはPCPコマンドが実行され、子プロセスが終了したこと、または新しいPCP worker プロセスが起動されるたことを示す正常動作のメッセージです。
pgpoo-II はどのように md5認証を行いますか?
- PostgreSQL、pgpool はそれぞれ pg_authid または pool_password に md5(password+username)を保存します。以後、これを "S" と称します。
- md5 認証が必要な場合、pgpool はフロントエンドにランダムな値 salt "s0" を送ります。
- フロントエンドがmd5(S+s0)をpgpool に返します。
- pgpool がpgpool_passwd から S を抽出し、md5(S+s0) を計算します。#3 と #4が一致する場合、次にステップに進みます。
- すべてのバックエンドがpgpool に salt を送ります。例えば、バックエンド b1、b2のsalts は s1 と s2。
- pgpool が pgpool_passwd から S を抽出し、 md5(S+s1)を計算し、バックエンド b1 に送ります。また、pgpool が pgpool_passwd から S を抽出し、 md5(S+s2)を計算し、バックエンド b2 に送ります。
- b1と b2 が認証に同意すると、md5 認証に成功します。
Pgpool-IIはなぜ自動的にデータベースがオンラインになったことを検知しないのですか?
- 技術的には可能ですが、安全ではない操作だからです。
- ストリミーングレプリケーション構成を考えてみてください。スタンバイがオンラインになったとしても、そのことはスタンバイが現在のプライマリに接続したことを必ずしも意味しません。違うプライマリに接続したかもしれませんし、そもそもスタンバイではないかもしれません。もしPgpool-IIがそのようなスタンバイを自動的にオンラインとして認識したら、そうしたスタンバイに送られたSELECTはプライマリとは違う結果を返すでしょうし、そうなったらデータベースアプリケーションにとっては災害状況になってしまいます。
- また、"pgpool reload"はスタンバイノードをオンラインとして認識することに関しては何も関係がないことに注意してください。それは単に設定ファイルを再読み込みするだけです。
- なお、Pgpool-II 4.1以降では、十分な安全が確認された時に自動的にスタンバイサーバをオンラインにする機能が追加されています。設定パラメータ"auto_failback"を参照してください。
idle_in_transaction_session_timeout を有効にした後、Pgpool-II が DB ノードの状態をすべて停止に設定します
- idle_in_transaction_session_timeout は PostgreSQL 9.6 で導入されました。アイドル状態のトランザクションをキャンセルするためのものです。
- 残念ながら、タイムアウトが発生した後、PostgreSQL は致命的なエラーを発生させ、fail_over_on_backend_error が on の場合、Pgpool-II でフェイルオーバを発生させます。
- 不要なフェイルオーバを回避するための方法がいくつかあります。
- fail_over_on_backend_error を無効にします。これにより、FATAL エラーが発生してもフェイルオーバは発生しなくなりますが、セッションは終了してしまいます。
- connection_life_time、child_life_time および client_idle_limit を idle_in_transaction_session_timeout より小さく設定します。FATAL エラーが発生しても、セッションは終了しなくなります。ただし、FATAL エラーが発生しない場合でも、1 つ以上の項目が指定された条件を満たす場合、コネクションプールは削除され、性能に影響を与える可能性があります。
Pgpool-II によって接続された PostgreSQL バックエンドの状態を知るにはどうすればよいですか?
- pg_stat_activity に表示されるバックエンドの状態は、「show pool_pools」コマンドを使用して調べることができます。「show pool_pools」で表示される列の 1 つ「pool_backendpid」は、対応する PostgreSQL バックエンドプロセスのプロセス ID です。それが分かったら、「pid」列と一致する pg_stat_activiy の出力を調べることができます。
- これは、PostgreSQL の dblink 拡張機能を使用して自動的に行うことができます。次にクエリの例を示します。
SELECT * FROM dblink('dbname=test host=xxx port=11000 user=t-ishii password=xxx', 'show pool_pools') as t1 (pool_pid int, start_time text, pool_id int, backend_id int, database text, username text, create_time text,majorversion int, minorversion int, pool_counter int, pool_backendpid int, pool_connected int), pg_stat_activity p WHERE p.pid = t1.pool_backendpid;
- 上記の SQL は、PostgreSQL または Pgpool-II のいずれかで実行できます。dblink の最初の引数は、PostgreSQL ではなく、Pgpool-II に接続するための接続文字列です。
Pgpool-II の Debian パッケージはどこで入手できますか?
- こちらから Debian パッケージを入手できます: https://apt.postgresql.org/pub/repos/apt/pool/main/p/pgpool2/
一般ユーザで Pgpool-II を起動する方法
- RPM から Pgpool-II をインストールすると、デフォルトの起動ユーザが root ユーザとなります。
- 一般ユーザでも Pgpool-II を起動することは可能です。しかし、仮想IP を制御するには root 権限が必要となります。そのため、一般ユーザが 仮想 IP の制御ができるように ip, ifconfig, arping に setuid を設定します。
- 以下は postgres で Pgpool-II を起動するための設定例です。
- pgpool.service ファイルを編集し、起動ユーザを postgres ユーザとする
# cp /usr/lib/systemd/system/pgpool.service /etc/systemd/system/pgpool.service # vi /etc/systemd/system/pgpool.service ... User=postgres Group=postgres ...
- /var/{lib,run}/pgpool ファイルの所有者を postgres ユーザに変更
# chown postgres:postgres /var/{lib,run}/pgpool # cp /usr/lib/tmpfiles.d/pgpool-II-pgxx.conf /etc/tmpfiles.d # vi /etc/tmpfiles.d/pgpool-II-pgxx.conf === d /var/run/pgpool 0755 postgres postgres - ===
- Pgpool-II 設定ファイルの所有者を postgres ユーザに変更
chown -R postgres:postgres /etc/pgpool-II/
- ip/ifconfig/arping コマンドを postgres ユーザのホームディレクトリにコピーし、setuid を設定します
# mkdir /var/lib/pgsql/sbin # chown postgres:postgres /var/lib/pgsql/sbin # chmod 700 /var/lib/pgsql/sbin # cp /sbin/ifconfig /var/lib/pgsql/sbin # cp /sbin/arping /var/lib/pgsql/sbin # cp /sbin/ip /var/lib/pgsql/sbin # chmod 4755 /var/lib/pgsql/sbin/ip # chmod 4755 /var/lib/pgsql/sbin/ # chmod 4755 /var/lib/pgsql/sbin/arping
repmgr をPgpool-IIと一緒に使うことはできますか?
- いいえ、使えません. これらのソフトウェアは、お互いのことを考慮していません。Pgpool-IIを使う時はrepmgerを使用すべきではありません。詳細はこちらを見てください: https://www.pgpool.net/pipermail/pgpool-general/2019-August/006743.html
CentOS6 で Pgpool-II への接続は失敗しました。
- Pgpool-IIはGSSAPI暗号化に対応していませんが、CentOS6ではGSSAPI接続が要求されます。 これにより、CentOS6で接続が失敗します。
- この問題を回避するために、CentOS6の環境で「export PGGSSENCMODE=disable」で環境変数を設定する必要があります。
watchdog のマスタが停止してもスタンバイがマスタを引き継ぎません
- watchdog ノードの数が偶数の場合は、4.1 の新機能である enable_consensus_with_half_votes パラメータを on にする必要があります。これが必要な理由は、4.1 のリリースノートで説明されています。
これは、偶数(すなわち、2, 4, 6...) watchdogクラスタにおけるクォーラムの存在および多数決の決定における振る舞いを変更します。 奇数のクラスタ(3, 5, 7...)は影響を受けません。 このパラメータがオフ(デフォルトです)の場合、2ノードのwatchdogクラスタは、クォーラムを持つためには2ノードの両方が生存している必要があります。 クォーラムが存在しないと、1) VIPが失われます 2) フェイルオーバスクリプトが実行されません 3) watchdogのマスターが存在しなくなります。 特に#2は、既存のPostgreSQLがダウンしても新しいプライマリが存在しなくなるので、困ったことになるでしょう。 おそらく2ノードのwatchdogクラスタユーザはi、このパラメータをオンにして、今までと同様に振る舞まうようにしたいでしょう。 一方4ノード以上の偶数watchdogクラスタユーザはこのパラメータがオフであることにメリットがあります。 なぜなら、半分のwatchdogノードがダウンしてsplit brainになる可能性を防ぐことができるからです。
pgpoolAdmin FAQ
pgpoolAdmin の pgpol status と node status にノード情報がありません。なぜですか?
- pgpoolAdmin は PHP の PostgreSQL エクステンション(pg_connect、pg_query など)を使います。おそらくエクステンションが期待通りに動作していません。apache のエラーログを確認してください。以下の FAQ も確認してください。
PostgreSQL が稼働中であるにもかかわらず、 pgpoolAdmin の node status が "down" ステータスを示しているのはなぜですか?
- pgpoolAdminは PostgreSQL のステータスを ユーザ = "health_check_user"、データベース = template1 と指定して接続することで監視しています。したがって、pgpoolAdmin が指定のユーザとデータベースにパスワードなしで PostgreSQL にアクセスできるようにする必要があります。PostgreSQL のログでこれを検証することができます。health_check_user が存在しないと以下のようなログが確認できます。:
20148 2011-07-06 16:41:59 JST FATAL: role "foo" does not exist
- If the user is protected by password, you will see:
20220 2011-07-06 16:42:16 JST FATAL: password authentication failed for user "foo" 20221 2011-07-06 16:42:16 JST LOG: could not receive data from client: Connection reset by peer 20221 2011-07-06 16:42:16 JST LOG: unexpected EOF within message length word 20246 2011-07-06 16:42:26 JST LOG: could not receive data from client: Connection reset by peer 20246 2011-07-06 16:42:26 JST LOG: unexpected EOF within message length word