pgpool2.git / summary / log / commit / refs

commit    7f529685e0db856bd8b67d3e614ef478ecce90b3
Author:   Yugo Nagata <nagata@sraoss.co.jp>
Date:     Wed Jun 06 02:41:14 2012 +0000

    Fix hangup when query conflict occurs in Hot-Standby mode.
    - Query example to reproduce:
      (S1) BEGIN;
      (S1) SELECT * FROM t;
      (S2) DELETE FROM t;
      (S2) VACUUM t;
    
    Fix SmpleQuery() to handle errors by calling check_errors().
    - Previously, check_errors() was called only in Execute().


pool_process_query.c | 14 ++++++++++++-- pool_proto_modules.c | 39 ++++++++++++++++++++++++++++++++------- pool_proto_modules.h | 2 +- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/pool_process_query.c b/pool_process_query.c index 281c118c2..d8d2b6141 100644 --- a/pool_process_query.c +++ b/pool_process_query.c @@ -4171,9 +4171,9 @@ int detect_deadlock_error(POOL_CONNECTION *backend, int major) return r; } -int detect_serialization_error(POOL_CONNECTION *backend, int major) +int detect_serialization_error(POOL_CONNECTION *backend, int major, bool unread) { - int r = detect_error(backend, SERIALIZATION_FAIL_ERROR_CODE, major, 'E', true); + int r = detect_error(backend, SERIALIZATION_FAIL_ERROR_CODE, major, 'E', unread); if (r == SPECIFIED_ERROR) pool_debug("detect_serialization_error: received serialization failure message from backend"); return r; @@ -4628,6 +4628,16 @@ SELECT_RETRY: if (FD_ISSET(CONNECTION(backend, i)->fd, &readmask)) { int r; + /* + * connection was terminated due to confilct with recovery + */ + r = detect_serialization_error(CONNECTION(backend, i), MAJOR(backend), false); + if (r == SPECIFIED_ERROR) + { + pool_log("connection on node %d was terminated due to conflict with recovery", i); + return POOL_ERROR; + } + /* * admin shutdown postmaster or postmaster goes down */ diff --git a/pool_proto_modules.c b/pool_proto_modules.c index 488bdde1f..261f18fb2 100644 --- a/pool_proto_modules.c +++ b/pool_proto_modules.c @@ -116,6 +116,7 @@ POOL_STATUS SimpleQuery(POOL_CONNECTION *frontend, char *string; int lock_kind; bool is_likely_select = false; + int specific_error = 0; POOL_SESSION_CONTEXT *session_context; POOL_QUERY_CONTEXT *query_context; @@ -582,15 +583,39 @@ POOL_STATUS SimpleQuery(POOL_CONNECTION *frontend, pool_query_context_destroy(query_context); return POOL_END; } + + /* Check specific errors */ + specific_error = check_errors(backend, MASTER_NODE_ID); + if (specific_error) + { + /* log error message */ + generate_error_message("SimpleQuery: ", specific_error, contents); + } } - /* - * Send the query to other than master node. - */ - if (pool_send_and_wait(query_context, -1, MASTER_NODE_ID) != POOL_CONTINUE) + if (specific_error) { - pool_query_context_destroy(query_context); - return POOL_END; + char msg[1024] = POOL_ERROR_QUERY; /* large enough */ + int len = strlen(msg); + + memset(msg + len, 0, sizeof(int)); + + /* send query to other nodes */ + query_context->rewritten_query = msg; + query_context->rewritten_length = len; + if (pool_send_and_wait(query_context, -1, MASTER_NODE_ID) != POOL_CONTINUE) + return POOL_END; + } + else + { + /* + * Send the query to other than master node. + */ + if (pool_send_and_wait(query_context, -1, MASTER_NODE_ID) != POOL_CONTINUE) + { + pool_query_context_destroy(query_context); + return POOL_END; + } } /* Send "COMMIT" or "ROLLBACK" to only master node if query is "COMMIT" or "ROLLBACK" */ @@ -3080,7 +3105,7 @@ static int check_errors(POOL_CONNECTION_POOL *backend, int backend_id) * M:S2:ERROR: could not serialize access due to concurrent update * S:S2:UPDATE t1 SET i = i + 1; <-- success in UPDATE and data becomes inconsistent! */ - if (detect_serialization_error(CONNECTION(backend, backend_id), MAJOR(backend)) == SPECIFIED_ERROR) + if (detect_serialization_error(CONNECTION(backend, backend_id), MAJOR(backend), true) == SPECIFIED_ERROR) return 2; /* diff --git a/pool_proto_modules.h b/pool_proto_modules.h index 68053b9c8..533a86bea 100644 --- a/pool_proto_modules.h +++ b/pool_proto_modules.h @@ -163,7 +163,7 @@ extern void query_ps_status(char *query, POOL_CONNECTION_POOL *backend); /* sho extern POOL_STATUS start_internal_transaction(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, Node *node); extern POOL_STATUS end_internal_transaction(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend); extern int detect_deadlock_error(POOL_CONNECTION *master, int major); -extern int detect_serialization_error(POOL_CONNECTION *master, int major); +extern int detect_serialization_error(POOL_CONNECTION *master, int major, bool unread); extern int detect_active_sql_transaction_error(POOL_CONNECTION *backend, int major); extern int detect_query_cancel_error(POOL_CONNECTION *backend, int major); extern bool is_partition_table(POOL_CONNECTION_POOL *backend, Node *node); [parent: da11bcdfa9c6]