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

Tatsuo Ishii ishii at sraoss.co.jp
Tue May 9 21:53:38 JST 2017


> On Tue, May 9, 2017 at 6:16 AM, Tatsuo Ishii <ishii at sraoss.co.jp> wrote:
> 
>> 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?
>>
> 
> 
> Waoo thanks for catching this, it is a really annoying issue, I think your
> patch does solve the problem and is the right approach,
> But I was thinking what if we move search for the primary node before
> starting the child processes. So that we spawn the child processes after
> finishing all the
> startup rituals?

Oh I think that will make even things safer.

> Do you think it will cause some issues?

So far there's nothing I can think of. Let me try it. I will report
back tomorrow.

Best regards,
--
Tatsuo Ishii
SRA OSS, Inc. Japan
English: http://www.sraoss.co.jp/index_en.php
Japanese:http://www.sraoss.co.jp


More information about the pgpool-hackers mailing list