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]