[pgsql-jp: 34006] Re: pgpoolのmaster データベース停止時の動作について( pgpool-2.0.9)

Tatsuo Ishii t-ishii @ sra.co.jp
2004年 9月 19日 (日) 22:03:11 JST


石井です.

> この度実際の業務システムでの使用を前提として、
> pgpoolを使用したレプリケーション機能の動作確認を行っております。
> 簡単な内容ではありますが、幾つかの障害ケースを人為的に発生させ、
> pgpool経由で接続している際にどのようなエラーが発生するのか
> パターンを洗い出しておりました。
> その際に、pgpoolがSQL文やpsqlコマンドに対して無反応になってしまう
> 現象が発生したため、そのことをご報告致します。
> 
> 本MLの過去のメールの中で、今年7月上旬の[pgsql-jp: 33449]から始まる
> 一連のスレッドにおいてケビン シュワンツ氏が報告された件と
> 現象がほぼ同じようです。
> 
> 以下、私の手元の環境構成と再現手順を列記します。

詳細な再現手順,ありがとうございます.

> ◎master側サーバー構成
>   Red Hat Enterprise Linux 3.0 ES
>   PostgreSQL 7.4.5 (本家RPM公開版)
>   pgpool 2.0.9 (tarball)
> 
> ◎secondary側サーバー構成
>   Red Hat Linux 9
>   PostgreSQL 7.4.5 (本家RPM公開版)
> 
> ◎主な設定変更点
>   ・pgpoolからmaster側PostgreSQLへはUNIXドメインソケット経由で、
>     secondary側PostgreSQLへはTCP/IP経由で接続しています。
>   ・master/secondaryともにPostgreSQLのポート番号を5433へ変更しています。  
> 
> ◎pgpool.conf
>   pgpool.conf.sampleから変更している設定項目は以下のとおりです。
> ------------------------------------------------------------
> allow_inet_domain_socket = true
> port = 5432
> backend_port = 5433
> secondary_backend_host_name = 'nnn.nnn.nnn.nnn'
> secondary_backend_port = 5433
> replication_mode = true
> ------------------------------------------------------------
> 
> ◎再現手順
> 1. masterおよびsecondaryのPostgreSQLを起動する。
>      # service postgresql start
> 
> 2. pgpoolを起動する。
>      $ pgpool -d -n
> 
> 3. psqlからpgpool経由でPostgreSQLに接続する。
>      $ psql -U hogehoge
> 
> 4. psqlより一回以上SQL文やpsqlコマンドを実行する。
> 
> 5. psqlを終了する。
> 
> 6. master側のPostgreSQLを停止する。
>      # service postgresql stop
> 
> 7. 再度psqlからpgpool経由でPostgreSQLに接続する。
>    この時点ではpgpoolはまだmaster側の停止を検知しておらず(?)
>    エラーが発生しないため、psqlのプロンプトまで正常に表示されます。

はい.コネクションプールを再利用する場合,7.4以降では接続時にバックエ
ンドとまったく通信する必要がないため,プロンプトが正常に表示されます.

> 8. psqlよりSQL文やpsqlコマンドを実行する。
>    ※pgpoolからの応答がなくなり、Ctrl+Cによるキャンセルもできなくなる。
>      show pool_statusコマンドの場合も応答がありません。
>      他から別にpsqlで接続を行うと、応答なしの状態が解消され、
>      接続に関するエラーメッセージが表示されます。

おそらく起きているのは以下のような現象です.

1) マスタがシャットダウン時にpgpoolにnotice messageを投げる

2) pgpoolはそれを受けとったので,セカンダリからもnotice messageが来る
   ものと思って待ち続ける

対策を色々考えたのですが,結局2)の時点でタイムアウトするしかないと思い
ました.しかし,ここで何も考えずにタイムアウトをかけると,時間のかかる
問い合わせを実行した際にもタイムアウトになってしまいます.そこで,問い
合わせを処理する際にマスタ側だけでなく,セカンダリの完了も待つことにし
ました.こうすると,正常ならば2)の時点では必ずセカンダリからすぐに応答
があるはずなので,タイムアウトするのは異常時だけと分かります.

というわけで,よろしくければ以下のパッチをお試し下さい.なお,このパッ
チは先日リリースしたばかりの2.1(ロードバランスの重み設定機能付)に対す
るものです.できれば2.1+パッチで試していただきたいのですが,どうしても
2.0.9でのテストが必要であれば教えてください.
--
Tatsuo Ishii

Index: pool_process_query.c
===================================================================
RCS file: /home/t-ishii/repository/pgpool/pool_process_query.c,v
retrieving revision 1.30
diff -c -r1.30 pool_process_query.c
*** pool_process_query.c	13 Sep 2004 00:05:10 -0000	1.30
--- pool_process_query.c	19 Sep 2004 12:45:49 -0000
***************
*** 283,289 ****
  			}
  			if (kind1 == 0)
  			{
! 				pool_read(SECONDARY(backend), &kind1, 1);
  			}
  			if (kind == '\0' || kind != kind1)
  			{
--- 283,306 ----
  			}
  			if (kind1 == 0)
  			{
! 				/* at this point the query has completed and it's safe to set timeout here */
! 				pool_debug("pool_process_query: waiting for secondary for data ready");
! 
! 				/* temporary enable timeout */
! 				pool_enable_timeout();
! 
! 				if (pool_check_fd(SECONDARY(backend), 0))
! 				{
! 					pool_error("pool_process_query: secondary data is not ready at syncronous point. abort this session");
! 
! 				}
! 				else
! 				{
! 					pool_read(SECONDARY(backend), &kind1, 1);
! 				}
! 
! 				pool_disable_timeout();
! 
  			}
  			if (kind == '\0' || kind != kind1)
  			{
***************
*** 492,497 ****
--- 509,519 ----
  		{
  			return POOL_END;
  		}
+ 
+ 		/* in "strict mode" we need to wait for secondary completing the query */
+ 		if (pool_config.replication_strict || STRICT_MODE(string))
+ 			if (synchronize(SECONDARY(backend)))
+ 				return POOL_END;
  	}
  	return POOL_CONTINUE;
  }



pgsql-jp メーリングリストの案内