[pgsql-jp: 35410] Re: pgpool経由のpg_dumpに失敗

Tatsuo Ishii t-ishii @ sra.co.jp
2005年 5月 23日 (月) 21:57:44 JST


石井です.

> 木村と申します。
> 
> pgpool-2.5経由のpg_dumpに失敗するという現象に遭遇しています。
> FreeBSD 4-STABLE上で、pgpoolでレプリケーションを行っているDBに対し、以
> 下のようにpg_dumpによるバックアップを試みました。DBはpg_dumpの出力(非
> 圧縮)で20MB程度と、かなり大きなものです。
> 
> %pg_dump db_name |bzip2 -c > backup.bz2
> 
> すると、途中でpg_dumpが以下のようなエラーを出力し、異常終了しました(ロ
> グ中、テーブル名等は伏せています)
> 
> >pg_dump: connection not open
> >pg_dump: lost synchronization with server, resetting connection
> >pg_dump: SQL command to dump the contents of table "****" failed: PQendcopy() failed.
> >pg_dump: Error message from server: pg_dump: The command was: COPY ****** (*****************) TO stdout;
> 
> pgpoolを-ndオプションで起動してログをとってみると、以下のようなエラー
> になっているようです(2行目)。
> 
> >DEBUG: pid 72959: pool_read_string: read all from pending data. po:98 len:7
> >ERROR: pid 72959: pool_flush: fflush failed (Resource temporarily unavailable)
> >DEBUG: pid 72959: Query: ABORT
> >DEBUG: pid 72959: read kind from backend pending data C len: 6 po: 99
> 
> どうもpool_steream.cの305行目の、fflushがEAGAINを返してそのままエラー
> になってる模様です。
> 
> 
> 次に、同じDBに対してパイプを使わずに以下のようにしてバックアップを取る
> と成功します。
> 
> %pg_dump db_name > backup
> %bzip2 backup
> 
> あまり良くわかってないのですが、パイプの受け先のbzip2の処理がいっぱい
> いっぱいになってパイプから読むのを一時停止 → pgpoolがflushしたので
> STDIOのバッファがあふれてエラーという事のような気がします。
> 
> 今のところ実運用上は上記のようにdumpとbzip2での圧縮を2段構えに分ければ
> 問題ないのですが、もしかすると本質的な問題として「あまりに大きなデータ
> を送受信すると、EAGAINでエラーになるかも知れない」ということがないもの
> かと気になりましたので報告します。
> 
> #パイプ経由にしてもたま〜に成功するし...やっぱりバッファの問題?

EAGAINが出ましたか.stdioライブラリの中でEAGAINのときは勝手にretryして
くれるのかと思っていたのですが...

とりあえず自前でretryするようにしてみました.以下のパッチを試していた
だけますか?
--
Tatsuo Ishii

RCS file: /cvsroot/pgpool/pgpool/pool_stream.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 pool_stream.c
*** pool_stream.c	14 Feb 2005 14:52:21 -0000	1.1.1.1
--- pool_stream.c	23 May 2005 12:57:51 -0000
***************
*** 300,317 ****
  */
  int pool_flush(POOL_CONNECTION *cp)
  {
! 	if (fflush(cp->write_fd) != 0)
  	{
  		pool_error("pool_flush: fflush failed (%s)", strerror(errno));
  
  		if (cp->isbackend)
  		{
! 		    notice_backend_error(!cp->issecondary_backend);
! 		    exit(1);
  		}
  		else
  		{
! 		    return -1;
  		}
  	}
  	return 0;
--- 300,325 ----
  */
  int pool_flush(POOL_CONNECTION *cp)
  {
! 	for (;;)
  	{
+ 		errno = 0;
+ 
+ 		if (fflush(cp->write_fd) == 0)
+ 			break;
+ 
+ 		if (errno == EAGAIN)
+ 			continue;
+ 
  		pool_error("pool_flush: fflush failed (%s)", strerror(errno));
  
  		if (cp->isbackend)
  		{
! 			notice_backend_error(!cp->issecondary_backend);
! 			exit(1);
  		}
  		else
  		{
! 			return -1;
  		}
  	}
  	return 0;



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