[pgpool-general-jp: 1145] レプリケーション遅延確認の不具合について

Hidenori Saitoh saitoh_hidenori_b1 @ lab.ntt.co.jp
2013年 3月 11日 (月) 12:17:10 JST


齋藤です。お世話になっております。

pgpool-II 3.2 において、log_standby_delay = if_over_thresholdとして、
ログを確認したところ、以下のようなメッセージが出力されました。

  2013-02-27 20:11:20 LOG: pid 17651: Replication of node:1 is behind -160 bytes from the primary server (node:0)

ここで、behind -160 bytes とマイナス値が出力されてしまっています。

ソースコードを確認したところ、次の箇所で出力されたログだと思われます。

pgpool-II-3.2.3/pool_worker_child.c
  check_replication_time_lag 関数内

  309行目
	pool_log("Replication of node:%d is behind %lld bytes from the primary server (node:%d)", i, lsn[PRIMARY_NODE_ID] - lsn[i], PRIMARY_NODE_ID);


このログの出力条件として、
	lag > pool_config->delay_threshold
が含まれています。
pool_config->delay_threshold より大きい値のときに
出力されるべきであり、マイナス値が出力されるのはおかしいと思われます。

ここで、lag は次の式より算出されています。
	lag = lsn[PRIMARY_NODE_ID] - lsn[i];

lag, lsn[] ともに、"unsigned long long int" 型で定義されています。
そのため、右辺の結果がマイナスになったとき、lag では正しく処理できておらず、
上記の lag > pool_config->delay_threshold の判定が誤ってしまっているのでは
ないでしょうか。

また、この算出結果の lag は、次の値に代入しています。
	bkinfo->standby_delay = lag;

この変数は、問合せの振り分け判定処理でも使われていると思われます。

マスタへの振り分け判定処理については、"pool_query_context.c" の
pool_where_to_send 関数の次の処理が該当すると思われます。

	/*
	 * If replication delay is too much, we prefer to send to the primary.
	 */
	if (!strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP) &&
		pool_config->delay_threshold &&
		bkinfo->standby_delay > pool_config->delay_threshold)
	{
		pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID);
	}

そのため、本来であれば、レプリケーション遅延が発生していない(しきい値よりも
小さい)状況であるにもかかわらず、マスタに振り分けされてしまう不具合が発生
するのではないでしょうか。

lsn[PRIMARY_NODE_ID] - lsn[i] の結果が負になる理由としては、
  ・lsn[PRIMARY_NODE_ID] は、マスタから SELECT pg_current_xlog_location() で取得
  ・lsn[i] は、スレーブからSELECT pg_last_xlog_replay_location() で取得
のように、別々に取得していることにより、タイミングによってずれが発生する
ためであると考えられます。

実際には、スレーブがマスタより進むということは発生しないため、
lsn[i] が lsn[PRIMARY_NODE_ID] より大きいときには、
lag の値を 0 (レプリケーション遅れなし) としておくのが良いかと
思いますがいかがでしょうか。

	if( lsn[PRIMARY_NODE_ID] > lsn[i] ){
		lag = lsn[PRIMARY_NODE_ID] - lsn[i];
	} else {
		lag = 0;
	}

または、「Primary_NODE_ID」のlsnは必ず最後に取得することで、
lsn[i] が lsn[PRIMARY_NODE_ID] より大きくなる事象を
回避できるのではないでしょうか。

よろしくお願い致します。


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