[pgpool-hackers: 2321] Corner case bug in primary failover

Tatsuo Ishii ishii at sraoss.co.jp
Tue May 9 10:16:53 JST 2017


Usama,

While adding a new test case to 003.failover regression test, I found
a corner case bug in primary failover.

Suppose Pgpool-II starts but is yet finding primary node. If primary
failover happens, it skips finding primary node and let the initial
value of it (Req_info->primary_node_id == -1) to be used as the new
primary node id. As a result, no primary node id exists until next
failover happens.

Initialy I thought The problem is in the code of
pgpool_main.c:failover() which tries to optimize finding primary node
process.

		/*
		 * If the down node was a standby node in streaming replication
		 * mode, we can avoid calling find_primary_node_repeatedly() and
		 * recognize the former primary as the new primary node, which
		 * will reduce the time to process standby down.
		 */
		else if (MASTER_SLAVE && pool_config->master_slave_sub_mode == STREAM_MODE &&
				 reqkind == NODE_DOWN_REQUEST)
		{
			if (Req_info->primary_node_id != node_id)
				new_primary = Req_info->primary_node_id;
			else
				new_primary =  find_primary_node_repeatedly();

I was attempting to fix it by checking Req_info->primary_node_id to
see if it's initial value (-1) or not. If it's -1,
find_primary_node_repeatedly() need to be called.

But looking into pgpool_main() closely, I suspect there's a
fundamental problem:

1) It processes failover in CHECK_REQUEST *before* setting
   Req_info->primary_node_id.

	/*
	 * check for child signals to ensure child startup before reporting successfull start
	 */
	CHECK_REQUEST;

	ereport(LOG,
			(errmsg("%s successfully started. version %s (%s)", PACKAGE, VERSION, PGPOOLVERSION)));

	/*
	 * if the primary node id is not loaded by watchdog, search for it
	 */
	if (Req_info->primary_node_id < 0)
	{
		/* Save primary node id */
		Req_info->primary_node_id = find_primary_node();
	}

2) It uses find_primary_node(), rather than
   find_primary_node_repeatedly(). So if by some reasons (for example
   the backend does not come up yet), find_primary_node() will fail
   and Req_info->primary_node_id is set to -1.

I think proper fix will be moving the CHECK_REQUEST call above inside
main loop, and change the find_primary_node() call to
find_primary_node_repeatedly().

Attached is the patch to do that (plus change the
search_primary_node_timeout to smaller value in 055.backend_all_down
test. Otherwise, regression timeout is triggered) against master
branch.

What do you think?
--
Tatsuo Ishii
SRA OSS, Inc. Japan
English: http://www.sraoss.co.jp/index_en.php
Japanese:http://www.sraoss.co.jp
-------------- next part --------------
A non-text attachment was scrubbed...
Name: failover.patch
Type: text/x-patch
Size: 2343 bytes
Desc: not available
URL: <http://www.sraoss.jp/pipermail/pgpool-hackers/attachments/20170509/3a548be8/attachment.bin>


More information about the pgpool-hackers mailing list