From f217239c0b92aaa6324c2c4ade8a3a7622af8a09 Mon Sep 17 00:00:00 2001 From: Tatsuo Ishii Date: Mon, 30 Jan 2017 16:30:57 +0900 Subject: [PATCH] Fix load balancing bug in streaming replication mode. In an explicit transaction, any SELECT will be load balanced until write query is sent. After writing query is sent, any SELECT should be sent to the primary node. However if a SELECT is sent before a sync message is sent, this does not work since the treatment of writing query is done after ready for query message arrives. Solution is, the treatment for writing query is done in executing the writing query as well. The bug has been there since V3.5. --- src/protocol/pool_proto_modules.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/protocol/pool_proto_modules.c b/src/protocol/pool_proto_modules.c index cde397be1..8f69636cf 100644 --- a/src/protocol/pool_proto_modules.c +++ b/src/protocol/pool_proto_modules.c @@ -901,6 +901,31 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, #ifdef NOT_USED pool_unset_query_in_progress(); #endif + + /* + * Take of "writing transaction" flag. + */ + if (!is_select_query(node, query)) + { + /* + * If the query was not READ SELECT, and we are in an + * explicit transaction, remember that we had a write + * query in this transaction. + */ + if (TSTATE(backend, MASTER_SLAVE ? PRIMARY_NODE_ID : REAL_MASTER_NODE_ID) == 'T') + { + /* However, if the query is "SET TRANSACTION READ ONLY" or its variant, + * don't set it. + */ + if (!pool_is_transaction_read_only(node)) + { + ereport(DEBUG1, + (errmsg("not SET TRANSACTION READ ONLY"))); + + pool_set_writing_transaction(); + } + } + } } return POOL_CONTINUE; -- 2.39.5