pgpool2.git / summary / log / commit / refs

commit    1ea486c29e8f3ff5d9b1ae69f32e2dde56bc0302
Author:   Tatsuo Ishii <ishii@postgresql.org>
Date:     Sat Mar 31 01:03:51 2012 +0000

    Allow to use multi statement in master/slave mode. From 3.1
    transactional statements such as "BEGIN" are sent to not only primary
    but also standbys. This brings an unfortunate side effect: if the
    multi statement is "BEGIN;DELETE FROM table;END", this will be sent to
    standy as well and cause an error because standby does not allow write
    SQL. So fix is, if a query is a multi statement one, then send it to
    primary only.
    
    Committed to master and V3_1_STABLE.


pool_proto_modules.c | 12 ++++++++++++ pool_query_context.c | 21 +++++++++++++++++++++ pool_query_context.h | 1 + 3 files changed, 34 insertions(+) diff --git a/pool_proto_modules.c b/pool_proto_modules.c index 4afff9542..b455be200 100644 --- a/pool_proto_modules.c +++ b/pool_proto_modules.c @@ -249,6 +249,18 @@ POOL_STATUS SimpleQuery(POOL_CONNECTION *frontend, */ pool_start_query(query_context, contents, len, node); + /* + * Check if multi statement query + */ + if (parse_tree_list && list_length(parse_tree_list) > 1) + { + query_context->is_multi_statement = true; + } + else + { + query_context->is_multi_statement = false; + } + if (PARALLEL_MODE) { bool parallel = true; diff --git a/pool_query_context.c b/pool_query_context.c index bd9fc1797..accc2942a 100644 --- a/pool_query_context.c +++ b/pool_query_context.c @@ -331,6 +331,27 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no { pool_set_node_to_be_sent(query_context, REAL_MASTER_NODE_ID); } + else if (MASTER_SLAVE && query_context->is_multi_statement) + { + /* + * If we are in master/slave mode and we have multi stametemt + * query, we should send it to primary server only. Otherwise + * it is possible to send a write query to standby servers + * because we only use the first element of the multi + * statement query and don't care about the rest. Typical + * situation where we are bugged by this is, "BEGIN;DELETE + * FROM table;END". Note that from pgpool-II 3.1.0 + * transactional statements such as "BEGIN" is unconditionaly + * sent to all nodes(see send_to_where() for more details). + * Someday we might be able to understand all part of multi + * statement queries, but until that day we need this band + * aid. + */ + if (query_context->is_multi_statement) + { + pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID); + } + } else if (MASTER_SLAVE) { POOL_DEST dest; diff --git a/pool_query_context.h b/pool_query_context.h index 5fb0940e4..e4a50e243 100644 --- a/pool_query_context.h +++ b/pool_query_context.h @@ -57,6 +57,7 @@ typedef struct { POOL_QUERY_STATE query_state[MAX_NUM_BACKENDS]; /* for extended query protocol */ bool is_cache_safe; /* true if SELECT is safe to cache */ POOL_TEMP_QUERY_CACHE *temp_cache; /* temporary cache */ + bool is_multi_statement; /* true if multi statement query */ } POOL_QUERY_CONTEXT; extern POOL_QUERY_CONTEXT *pool_init_query_context(void); [parent: a29cd65a642c]