負荷分散

Pgpool-II 3.6.5 文書
前のページ | 上に戻る | 第 5章サーバの設定 | 次のページ

# 5.7. 負荷分散

Pgpool-IIのSELECTクエリの負荷分散はマスタースレーブモード（項5.3.1）とレプリケーションモード（項5.3.2）で動作します。 有効時、Pgpool-IIは更新を伴うクエリを、マスタースレーブモードではプライマリノードに、レプリケーションモードでは全てのバックエンドノードに対し送信します。 そして、その他のクエリは全てのバックエンドの間で負荷分散されます。 負荷分散メカニズムが参照クエリをどのノードに送信するかはセッション開始時に決められ、セッションの終了まで変更されません。 唯一の例外は特別なSQLコマンドが発行されたときです。 詳細については以下をご覧ください。

> 注意: 負荷分散ができないためにプリマリノードまたは全バックエンドノードに送られクエリもまた、負荷分散アルゴリズムで判断されます。

> 注意: もし負荷分散対象のクエリをPgpool-IIに負荷分散してほしくない場合には、SELECT文の前の/*NO LOAD BALANCE*/コメントを付与することができます。 これにより、そのクエリの負荷分散は無効となり、Pgpool-IIはこれをマスターノード（マスタースレーブモードではプライマリノード）に送信します。

> 注意: どのDBノードが負荷分散ノードになっているかは、SHOW POOL NODESを利用して確認できます。

## 5.7.1. 負荷分散の条件について

クエリが負荷分散されるためには、以下の全ての条件を満たす必要があります：

- PostgreSQLのバージョンが7.4以降である

- レプリケーションモードまたはマスタースレーブモードである

- 問い合わせが明示的なトランクザションブロックの内側にない(つまり、BEGINを発行していない)

  - ただし、以下の条件が満たされればトランザクションブロックの内側であっても負荷分散の対象となります。

    - トランザクション分離レベルがSERIALIZABLEでない

    - トランザクション内で更新を伴うクエリが実行されていない (更新を伴うクエリが実行されるまでは負荷分散されます。 ここで「更新を伴うクエリ」とは、SELECT以外のDDLやDMLを指します。 black/white function listで指定される更新関数を含むSELECTは更新を伴うクエリとは見なされません。 この仕様は将来変更される可能性があります)

    - もしblack/white function listが空の場合は、関数を持つSELECTは、更新を伴うクエリとは見なされません。

- SELECT INTO 文ではない

- SELECT FOR UPDATE/SELECT FOR SHARE文ではない

- SELECT または COPY TO STDOUT, EXPLAIN, EXPLAIN ANALYZE SELECT... から始まる。 (black_function_listまたはwhite_function_listで指定された書き込み関数を含むSELECTを除く) ignore_leading_white_space = `true`の場合は最初の空白文字は無視されます。

- マスタースレーブモードの場合、更に以下の条件が満たされなければなりません。

  - 一時テーブルを使っていない

  - unloggedテーブルを使っていない

  - システムカタログを使っていない

> 注意: SELECTクエリの前に任意のコメントを挿入することにより負荷分散を抑制することができます。

>     /*REPLICATION*/ SELECT ...

> SQLコメントの記述が負荷分散に影響を与えないようにするには、allow_sql_commentsをonにします。 replicate_selectも参照してください。

> 注意: JDBC ドライバにはautocommitオプションがあります。 autocommit を無効にすると、ドライバが内部でBEGINおよびCOMMITコマンドを実行し、明示的なトランザクションが開始されます。 この場合、トランザクション内における上記の負荷分散の制限事項が適用されます。

## 5.7.2. ストリーミングレプリケーションにおける負荷分散

ストリーミングレプリケーションとHot Standbyを利用している環境では、プライマリノードに送ってよい問い合わせ、スタンバイに送ってもよい問い合わせ、両方に送らなければならない問い合わせを厳密に管理する必要があります。 Pgpool-IIのストリーミングレプリケーションモードは、こうした振り分けを自動的に行ないます。

クエリそのものから、どのクエリがどのノードに送られるべきかを区別します。

- プライマリノードにしか送られない問い合わせ

  - INSERT, UPDATE, DELETE, COPY FROM, TRUNCATE, CREATE, DROP, ALTER, COMMENT

  - SELECT ... FOR SHARE | UPDATE

  - トランザクションの分離レベルがシリアライザブルの場合のSELECT

  - OW EXCLUSIVE MODEよりも強いLOCK

  - DECLARE, FETCH, CLOSE

  - SHOW

  - トランザクションコマンドの一部

    - BEGIN READ WRITE, START TRANSACTION READ WRITE

    - SET TRANSACTION READ WRITE, SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE

    - SET transaction_read_only = off

  - 二相コミット関連のコマンド。PREPARE TRANSACTION, COMMIT PREPARED, ROLLBACK PREPARED

  - LISTEN, UNLISTEN, NOTIFY

  - VACUUM

  - シーケンス関連の関数(nextvalやsetvalなど)の呼び出し。

  - ラージオブジェクトの生成

- プライマリノードとスタンバイノードのどちらにも送ることのできる問い合わせ。 負荷分散設定が有効ならば、スタンバイノードにも送信されます。 レプリケーションの遅延がdelay_thresholdを上回っている場合は問い合わせはプライマリノードに送られます。

  - SELECT not listed above

  - COPY TO

- プライマリノードとスタンバイノードのどちらにも送られる問い合わせ

  - SET

  - DISCARD

  - DEALLOCATE ALL

明示的なトランザクションでは、以下のようになります。

- BEGINなどのトランザクション開始コマンドは、プライマリノードに送られます。

- 続くSELECTなど、プライマリ/スタンバイのどちらにも送ることのできる問い合わせは、プライマリのトランザクション内でそのまま実行されるか、スタンバイノードで実行されます。

- INSERTなど、スタンバイに送ることのできない問い合わせが現われた場合はプライマリに送られます。 そういったコマンドの後は、SELECTであってもプライマリノードに送られます。 これは、INSERTなどの問い合わせの結果を SELECTが直ちに参照できるようにするためです。 この状態は、トランザクションが閉じるか、アボートするまで続きます。

問い合わせが、拡張問い合わせモードで実行される場合は、問い合わせのparse段階で、問い合わせがスタンバイに送信可能かが決まります。 その際の判断ルールは通常のSQLと同じです。 たとえば問い合わせがINSERTならば、プライマリノードに送られます。 それに後に続くbind, describe, executeも同じくプライマリに送られます。

> 注意: 負荷分散によりSELECT文のparseがスタンバイノードに送信され、その後INSERTなどのDML文がPgpool-IIに送られた場合、parse済のSELECTはプライマリノードで実行されなければなりません。 そのため、同じSELECTがプライマリノードで再度パースされることになります。

最後に、pgpool-IIのパーサが構文エラーと判断した問い合わせはプライマリノードだけに送られます。

## 5.7.3. 負荷分散の設定

`load_balance_mode` (`boolean`)

  onの設定すると、Pgpool-IIは入ってきたSELECTクエリに対する負荷分散を有効にします。 すなわち、クライアントからのSELECTクエリは設定されたPostgreSQLバックエンドに振り分けます。 デフォルトはoffです。

  このパラメータはサーバ起動時にのみ設定可能です。

`ignore_leading_white_space` (`boolean`)

  onに設定すると、負荷分散の際にSQL文行頭の空白を無視します(全角スペースは無視されません)。 これは、DBI/DBD:Pgのように、ユーザの意図に反してに空白を追加するようなAPIを使っているときに有用です。

  このパラメータはPgpool-IIの設定を再読み込みすることで変更可能です。

`white_function_list` (`string`)

  データベースに対して更新を行なわない関数名をコンマ区切りで指定します。 このリストに指定されていない関数呼び出しを含むSELECTは負荷分散されません。 これらのクエリはレプリケーションモードにおいてはすべてのDBノードで複製され、マスタースレーブモードにおいてはプライマリノードにのみ送信されます。

  関数名のマッチングに正規表現を使うことができます。 正規表現には自動的に`^`と`$`が付与されます。

  例 5-2. 正規表現の使用

  もし読み出しのみを行う関数が"get_"あるいは"select_"で始まるようにしてあるのであれば、white_function_listを以下のように設定可能です。

      white_function_list = 'get_.*,select_.*'

  このパラメータはPgpool-IIの設定を再読み込みすることで変更可能です。

`black_function_list` (`string`)

  データベースに対して更新を行う関数名をコンマ区切りで指定します。 このリストに指定された関数呼び出しを含むSELECTは負荷分散されません。 これらのクエリはレプリケーションモードにおいてはすべてのDBノードで複製され、マスタースレーブモードにおいてはプライマリノードにのみ送信されます。

  関数名のマッチングに正規表現を使うことができます。 正規表現には自動的に`^`と`$`が付与されます。

  例 5-3. 正規表現の使用

  もし更新を行う関数が"set_"、"update_"、"delete_"、あるいは"insert_"で始まるようにしてあるのであれば、black_function_listを以下のように設定可能です。

      black_function_list = 'nextval,setval,set_.*,update_.*,delete_.*,insert_.*'

  > 注意: black_function_listとwhite_function_listは互いに排他的で、２つのリストの内、どちらか一方のみ設定することができます。

  例 5-4. `nextval()`と`setval()`を適切なバックエンドに送る設定

  Pgpool-II V3.0より前のバージョンでは、固定で`nextval()`と`setval()`がデータベースに書き込みを行なう関数であると認識されていました。 以下のようにblack_function_listとblack_function_listを設定することで、それと同じように動作させることができます。

      white_function_list = ''
      black_function_list = 'nextval,setval,lastval,currval'

  > 注意: PostgreSQLには`nextval()`と`setval()`に加え、`lastval()`と`currval`があります。 `lastval()`と`currval()`は書き込みを行う関数ではありませんが、これらの関数が負荷分散されることで発生するエラーを防ぐため、`lastval()`と`curval()`を書き込みを行う関数として扱うのが望ましいです。

  このパラメータはPgpool-IIの設定を再読み込みすることで変更可能です。

`database_redirect_preference_list` (`string`)

  特定のデータベース接続ではSELECTクエリが特定のバックエンドノードに送信されるように、"`データベース名:ノードID`"ペアのリストを指定します。 たとえば"test:1"とした場合、"test"データベースへの接続においては、Pgpool-IIは全てのSELECTクエリをIDが1のバックエンドノードに送信します。 複数の"`データベース名:ノードID`"のペアを カンマ(,)で区切って指定することができます。

  データベース名には正規表現を指定することできます。 `ノードID`には特別なキーワードを使うことができます。 "primary"が指定された場合にはクエリはプライマリノードに送られます。 また、"standby"が指定された場合はスタンバイノードのうちどれかをウェイトに応じてランダムに選択します。

  例 5-5. database_redirect_preference_listの利用

  SELECTクエリのルーティングルールを以下のように設定したい場合：

  - 全ての`postgres`データベースにおけるSELECTクエリはプライマリバックエンドノードに送る。

  - 全ての`mydb0`または`mydb1`データベースにおけるSELECTクエリはIDが1のバックエンドノードに送る。

  - 全ての`mydb2`データベースにおけるSELECTクエリはスタンバイバックエンドノードに送る。

  database_redirect_preference_listは以下のように設定します。

      database_redirect_preference_list = 'postgres:primary,mydb[01]:1,mydb2:standby'

  このパラメータはPgpool-IIの設定を再読み込みすることで変更可能です。

`app_name_redirect_preference_list` (`string`)

  特定のクライアントアプリケーションの接続ではSELECTクエリが特定のバックエンドノードに送信されるように、"`アプリケーション名:ノードID`"ペアのリストを指定します。

  > 注意: 「アプリケーション名」とはクライアントがデータベースに接続する時に指定する名称で、PostgreSQL V9.0以降で利用可能です。

  たとえば、`psql`コマンドのアプリケーション名は"`psql`"です。

  > 注意: Pgpool-IIは、クライアントから送信されたスタートアップパケットに含まれるアプリケーション名だけを認識します。 クライアントは事後にセッションの中でアプリケーション名を指定できますが、それはPgpool-IIのクエリルーティングでは考慮されません。

  app_name_redirect_preference_listの記法はdatabase_redirect_preference_listと同じですので、アプリケーション名には正規表現も使用できます。 同様に特別なキーワード"primary"はプライマリノードを、"standby"はスタンバイサーバのいずれかを意味します。

  例 5-6. app_name_redirect_preference_listの利用

  SELECTクエリのルーティングルールを以下のように設定したい場合：

  - 全ての`psql`クライアントからのSELECTクエリはプライマリバックエンドノードに送る。

  - 全ての`myapp1`クライアントからのSELECTクエリはIDが1のバックエンドノードに送る。

  - 全ての`myapp2`クライアントからのSELECTクエリはスタンバイバックエンドノードに送る。

  app_name_redirect_preference_listは以下のように設定します。

      app_name_redirect_preference_list = 'psql:primary,myapp1:1,myapp2:standby'

  > 注意: app_name_redirect_preference_listは、database_redirect_preference_listよりも優先されます。

  注意
  JDBCドライバのpostgresql-9.3以前のバージョンでは、JDBCドライバの"`ApplicationName`" と "`assumeMinServerVersion=9.0`"オプションを指定してもスタートアップパケットの中にアプリケーション名を含ません。 JDBCからapp_name_redirect_preference_list機能を使用したければ、postgresql-9.4 以降のドライバをお使いください

  このパラメータはPgpool-IIの設定を再読み込みすることで変更可能です。

`allow_sql_comments` (`boolean`)

  onに設定すると、Pgpool-IIは負荷分散やクエリキャッシュができるかどうかの判定の際にSQLコメントを無視します。 このパラメータがoffに設定されている場合、クエリのSQLコメントにより、クエリの負荷分散やキャッシュを防止することができます。 （Pgpool-II V3.4より前のバージョンの動作です）。

  このパラメータはPgpool-IIの設定を再読み込みすることで変更可能です。 現在のセッションでのパラメータ値は、PGPOOL SETコマンドで変更することもできます。

前のページ | ホーム | 次のページ
エラー報告とログ取得 | 上に戻る | ヘルスチェック