[pgpool-general-jp: 617] Re: オンラインリカバリ時のBackendErrorについて

Tatsuo Ishii ishii @ sraoss.co.jp
2009年 9月 3日 (木) 13:00:10 JST


詳細なレポートありがとうございます。石井です。

> お世話になっております。田辺です。
> 先日のメールについて補足させてください。
> 
> child.c:Req_info->conn_counterに注目し、child.c:connection_count_down()
> の直後にReq_info->conn_counterの値をpool_log()を使ってログ出力させたとこ
> ろ、値がマイナス(-1)になっていました。
> 
> ここから推測すると、このために、オンラインリカバリ時に
> recovery.c:wait_connection_closed()内
>                 if (Req_info->conn_counter == 0)
> が満たされず、クライアントのクローズ待ちがタイムアウトしているように見え
> ます。
> 
> レプリケーションしているPostgreDBの停止には、
> 
>  (a) pg_ctl stop -D /usr/local/pgsql/data
>  (b) pg_ctl stop -D /usr/local/pgsql/data -s -m fast
> 
> を使いました。本事象は、両方で発生するのですが、(b)の方がより発生しやす
> いです。
> 
> そこで質問なのですが、
>  (1) カウンタがマイナス値になることは想定通りの動作でしょうか?

いえ。

>  (2) 上記(1)の回答で”想定通りでない”場合、回避方法はありますでしょう
> か?

必ずしもリカバリ中にこの現象が発生しないのだとすると、シグナル割り込み
などのタイミングの問題で、どこかでカウンタを余計に減算していると思われ
ます。そうなると、ソースコードの修正以外には対応方法はないと思います。

>  (3) Postgresの停止として、-m fastの利用は許されていないのでしょうか?

いえ、そんなことはありません。

>  (4) カウンタがマイナス値になった場合の検出方法やリセット方法はあります
> でしょうか?

カウンタを余計に減算していそうな箇所があったので、修正パッチを作ってみ
ました。可能であれば、添付のパッチを試してみていただけますでしょうか?

>  質問を書き連ねて申し訳ありませんが、ご教授いただけないでしょうか。
> 
>  以上、よろしくお願いします。
> 
> 
> 
> 
> Date:Fri, 21 Aug 2009 15:08:34 +0900
> From:Ryoichi TANABE <r-tanabe @ nsat.co.jp>様
> To:pgpool-general-jp @ sraoss.jp
> Cc:--
> > 初めまして。田辺と申します。
> > 掲題の件に関し質問させていただきたくメールしました。
> > 
> > オンラインリカバリの 2ndステージに入ったところで、クライアントプログラ
>> > が、DB接続完了待ちになり、リカバリタイムアウト(recovery_timeout)まで処
>> > が戻りません。オンラインリカバリは、タイムアウトしたところで
> BackendError
> > エラーで失敗します。
> > 
> > PGPool側での2nd ステージ開始時のクライアント接続の終了待ち と
> > クライアントプログラムでのDB接続完了待ち とが
> > 互いに待ち続けているように見えています。
> > 
> > v2.2.2ではこのように互いに待ち続けているようなことはありませんでした。
> > 
> > 対処法などございましたらご回答の程よろしくお願いします。
> > 
> > 
> > 
> > 
> > ※PGPoolのログより抜粋
> > 2009-08-20 14:08:22 LOG:   pid 27568: starting 2nd stage
> > 2009-08-20 14:14:25 ERROR: pid 27568: wait_connection_closed: existing 
> > connections did not close in 360 sec.
> > 2009-08-20 14:14:25 ERROR: pid 27568: start_recovery: timeover for 
> > waiting connection closed
> > 
> > ※pgpool.confより抜粋
> > recovery_timeout = 360
> > client_idle_limit_in_recovery = 240
> > 
> > ※クライアントプログラムはPythonで作成しいます
> > ※クライアントプログラムは、常駐プロセスで、
> >   pgdb.connect() -> cursor.executemany() -> db.commit() -> db.close()
> >  を繰り返しています。pgdb.connect()で処理が止まっている状態になります
> > ※システム構成情報
> >  PGPool-II  : v2.2.3
> >  PostgreSQLl: 8.3.7
> >  OS         : CentOS5
> >  Python     : 2.5.1
> >  DB-API     : PyGreSQL-4.0
> >  2ノードのレプリケーションモード
> > 
> > 以上
> > -----------
> > 田辺亮一
> > _______________________________________________
> > pgpool-general-jp mailing list
> > pgpool-general-jp @ sraoss.jp
> > http://www.sraoss.jp/mailman/listinfo/pgpool-general-jp
> 
> 
> -----------
> 田辺亮一
> _______________________________________________
> pgpool-general-jp mailing list
> pgpool-general-jp @ sraoss.jp
> http://www.sraoss.jp/mailman/listinfo/pgpool-general-jp
-------------- next part --------------
Index: child.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/child.c,v
retrieving revision 1.26.2.7
diff -c -r1.26.2.7 child.c
*** child.c	22 Aug 2009 04:19:49 -0000	1.26.2.7
--- child.c	3 Sep 2009 03:57:08 -0000
***************
*** 68,73 ****
--- 68,75 ----
  static int send_params(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend);
  static void send_frontend_exits(void);
  static int s_do_auth(POOL_CONNECTION_POOL_SLOT *cp, char *password);
+ static void connection_count_up(void);
+ static void connection_count_down(void);
  
  /*
   * non 0 means SIGTERM(smart shutdown) or SIGINT(fast shutdown) has arrived
***************
*** 1774,1790 ****
  	return -1;
  }
  
! void connection_count_up(void)
  {
  	pool_semaphore_lock(CONN_COUNTER_SEM);
  	Req_info->conn_counter++;
  	pool_semaphore_unlock(CONN_COUNTER_SEM);
  }
  
! void connection_count_down(void)
  {
  	pool_semaphore_lock(CONN_COUNTER_SEM);
! 	Req_info->conn_counter--;
  	pool_semaphore_unlock(CONN_COUNTER_SEM);
  }
  
--- 1776,1809 ----
  	return -1;
  }
  
! /*
!  * Count up connection counter (from frontend to pgpool)
!  * in shared memory
!  */
! static void connection_count_up(void)
  {
  	pool_semaphore_lock(CONN_COUNTER_SEM);
  	Req_info->conn_counter++;
  	pool_semaphore_unlock(CONN_COUNTER_SEM);
  }
  
! /*
!  * Count down connection counter (from frontend to pgpool)
!  * in shared memory
!  */
! static void connection_count_down(void)
  {
  	pool_semaphore_lock(CONN_COUNTER_SEM);
! 	/*
! 	 * Make sure that we do not decrement too much.  If failed to read
! 	 * a start up packet, or receive cancel request etc.,
! 	 * connection_count_down() is called and goes back to the
! 	 * connection accept loop. Problem is, at the very beginning of
! 	 * the connection accept loop, if we have received a signal, we
! 	 * call child_exit() which calls connection_count_down() again.
! 	 */
! 	if (Req_info->conn_counter > 0)
! 		Req_info->conn_counter--;
  	pool_semaphore_unlock(CONN_COUNTER_SEM);
  }
  
Index: pool.h
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool.h,v
retrieving revision 1.36.2.4
diff -c -r1.36.2.4 pool.h
*** pool.h	22 Jul 2009 08:46:55 -0000	1.36.2.4
--- pool.h	3 Sep 2009 03:57:14 -0000
***************
*** 528,536 ****
  extern void pool_free_startup_packet(StartupPacket *sp);
  extern void child_exit(int code);
  
- extern void connection_count_up(void);
- extern void connection_count_down(void);
- 
  extern int health_check(void);
  extern int system_db_health_check(void);
  
--- 528,533 ----


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