summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pool_process_query.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/pool_process_query.c b/pool_process_query.c
index d61cc3f..9aac9ae 100644
--- a/pool_process_query.c
+++ b/pool_process_query.c
@@ -160,6 +160,7 @@ static int master_slave_was_enabled; /* master/slave mode was enabled */
static int internal_transaction_started; /* to issue table lock command a transaction
has been started internally */
static int select_in_transaction = 0; /* non 0 if select query is in transaction */
+static int extended_select = 0; /* non 0 if extended mode */
static int in_progress = 0;
static void (*pending_function)(PreparedStatementList *p, PreparedStatement *statement) = NULL;
@@ -737,6 +738,7 @@ static POOL_STATUS Query(POOL_CONNECTION *frontend,
REPLICATION = 0;
in_load_balance = 1;
select_in_transaction = 1;
+ extended_select = 0;
}
/*
@@ -891,6 +893,7 @@ static POOL_STATUS Execute(POOL_CONNECTION *frontend,
REPLICATION = 0;
in_load_balance = 1;
select_in_transaction = 1;
+ extended_select = 1;
}
}
@@ -2815,8 +2818,10 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C
pending_function(&prepared_list, pending_prepared_stmt);
}
else if (kind == 'C' && select_in_transaction)
+ {
select_in_transaction = 0;
-
+ extended_select = 0;
+ }
/*
* Remove a pending function if a received message is not
* NoticeResponse.
@@ -2882,6 +2887,7 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C
{
int i, k;
int res1, res2;
+ int sync_secondary = 1;
char *p1;
/*
@@ -2919,6 +2925,11 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C
do_error_command(SECONDARY(backend), PROTO_MAJOR_V3);
}
select_in_transaction = 0;
+ if (extended_select)
+ {
+ sync_secondary = 0;
+ extended_select = 0;
+ }
}
for (i = 0;i < backend->num;i++)
@@ -2931,6 +2942,20 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C
* it by itself. Moreover we do not need it in non-extend mode.
* At this point we regard it is not harmfull since error resonse
* will not be sent too frequently.
+
+ * We observed a process stall at the synchronous
+ * point (Line 370 of this code) in this situation:
+ * 1. replicate_select = false
+ * 2. do extended select for MASTER, and get some error
+ * 3. do_error_command for SECONDARY,
+ * 4. send Sync to both MASTER and SECONDARY
+ * 5. SECONDARY returns something but MASTER doesn't.
+ * 6. then pgpool stalls at pool_read on #370 to wait
+ * for a response from MASTER.
+ *
+ * To avoid this situation, we introduced a variable
+ * 'extended_select' so that pgpool sends Sync only to
+ * MASTER when the query is in extended mode.
*/
pool_write(cp, "S", 1);
res1 = htonl(4);
@@ -2939,7 +2964,7 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C
return POOL_END;
}
- if (!DUAL_MODE)
+ if (!DUAL_MODE || sync_secondary == 0)
break;
}