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]