pgpool2.git / summary / log / commit / refs

commit    a2d04ab99b8be678053106a4449c512c5bb74e04
Author:   Tatsuo Ishii <ishii@postgresql.org>
Date:     Wed May 25 00:32:46 2016 +0000

    Deal with the case when the primary is not node 0 in streaming replication mode.
    
    http://www.pgpool.net/mantisbt/view.php?id=194#c837 reported that if
    primary is not node 0, then statement timeout could occur even after
    bug194-3.3.diff was applied. After some investigation, it appeared
    that MASTER macro could return other than primary or load balance
    node, which was not supposed to happen, thus do_query() sends queries
    to wrong node (this is not clear from the report but I confirmed it in
    my investigation).
    
    pool_virtual_master_db_node_id(), which is called in MASTER macro
    returns query_context->virtual_master_node_id if query context
    exists. This could return wrong node if the variable has not been set
    yet. To fix this, the function is modified: if the variable is not
    either load balance node or primary node, the primary node id is
    returned.
    
    For master and 3.5-stable, additional fixes/enhancements are made:
    pool_extended_send_and_wait() now issues flush message if the request
    is 'E' (execute). Before it was issued outside (in Execute), but this
    makes the logic to determine to which node the flush message to be
    sent unnecessary complex.
    
    A debug message in pool_write is enhanced by adding backend node id.


src/context/pool_query_context.c | 34 +++++++++++++++++++++++++++++++++- src/protocol/pool_proto_modules.c | 6 +++++- src/utils/pool_stream.c | 2 +- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/context/pool_query_context.c b/src/context/pool_query_context.c index 8f3eb8a46..49b005606 100644 --- a/src/context/pool_query_context.c +++ b/src/context/pool_query_context.c @@ -27,6 +27,7 @@ #include "utils/memutils.h" #include "utils/elog.h" #include "utils/pool_select_walker.h" +#include "utils/pool_stream.h" #include "context/pool_session_context.h" #include "context/pool_query_context.h" #include "parser/nodes.h" @@ -279,7 +280,23 @@ int pool_virtual_master_db_node_id(void) if (sc->query_context) { - return sc->query_context->virtual_master_node_id; + int node_id = sc->query_context->virtual_master_node_id; + + if (STREAM) + { + /* + * Make sure that virtual_master_node_id is either primary node + * id or load balance node id. If not, it is likely that + * virtual_master_node_id is not set up yet. Let's use the + * primary node id. + */ + if (node_id != sc->load_balance_node_id && node_id != PRIMARY_NODE_ID) + { + node_id = PRIMARY_NODE_ID; + } + } + + return node_id; } /* @@ -860,6 +877,21 @@ POOL_STATUS pool_extended_send_and_wait(POOL_QUERY_CONTEXT *query_context, } send_extended_protocol_message(backend, i, kind, str_len, str); + + if (*kind == 'E' && STREAM) + { + /* + * Send flush message to backend to make sure that we get any response + * from backend in Sream replication mode. + */ + + POOL_CONNECTION *cp = CONNECTION(backend, i); + int len; + + pool_write(cp, "H", 1); + len = htonl(sizeof(len)); + pool_write_and_flush(cp, &len, sizeof(len)); + } } if (!is_begin_read_write) diff --git a/src/protocol/pool_proto_modules.c b/src/protocol/pool_proto_modules.c index 9537ec7aa..6277b6135 100644 --- a/src/protocol/pool_proto_modules.c +++ b/src/protocol/pool_proto_modules.c @@ -802,6 +802,7 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, pool_extended_send_and_wait(query_context, "E", len, contents, 1, MASTER_NODE_ID, true); pool_extended_send_and_wait(query_context, "E", len, contents, -1, MASTER_NODE_ID, true); +#ifdef NOT_USED /* * Send flush message to backend to make sure that we get any response * from backend. @@ -809,6 +810,7 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, pool_write(MASTER(session_context->backend), "H", 1); len = htonl(sizeof(len)); pool_write_and_flush(MASTER(session_context->backend), &len, sizeof(len)); + if (MASTER(session_context->backend)->db_node_id != session_context->load_balance_node_id) { POOL_CONNECTION *con; @@ -818,6 +820,7 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, len = htonl(sizeof(len)); pool_write_and_flush(con, &len, sizeof(len)); } +#endif /* * Remeber that we send flush or sync message to backend. */ @@ -829,6 +832,7 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, return POOL_CONTINUE; } + /* * process Parse (V3 only) */ @@ -3268,4 +3272,4 @@ flatten_set_variable_args(const char *name, List *args) } return buf.data; -} \ No newline at end of file +} diff --git a/src/utils/pool_stream.c b/src/utils/pool_stream.c index 72690541f..7249b3be2 100644 --- a/src/utils/pool_stream.c +++ b/src/utils/pool_stream.c @@ -428,7 +428,7 @@ int pool_write_noerror(POOL_CONNECTION *cp, void *buf, int len) c = ((char *)buf)[0]; ereport(DEBUG1, - (errmsg("pool_write: to backend: kind:%c", c))); + (errmsg("pool_write: to backend: %d kind:%c", cp->db_node_id, c))); } while (len > 0) [parent: 655caa9c179d]