In commit
8640abfc41ff06b1e6d31315239292f4d3d4191d,
pool_wait_till_ready_for_query() was introduced to retrieve all
messages into buffer from backend until it found a "ready for query"
message when extended query protocol is used in streaming replication
mode. It could hit memory allocation limit of palloc(), which is 1GB.
This could be easily reproduced by using pgbench and pgproto for
example.
pgbench -s 100
pgproto data:
'P' "" "SELECT * FROM pgbench_accounts" 0
'B' "" "" 0 0 0
'E' "" 0
'S'
'Y'
To reduce the memory usage, introduce "suspend_reading_from_frontend"
flag in session context so that Pgpool-II does not read any message
after sync message is received. The flag is turned off when a "ready
for query" message is received from backend. Between this, Pgpool-II
reads messages from backend and forward to frontend as usual. This way
we could eliminate the necessity to store messages from backend in
buffer, thus it reduces the memory foot print.
Per bug 462.
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2018 PgPool Global Development Group
+ * Copyright (c) 2003-2019 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
/* Backends have not ignored messages yet */
pool_unset_ignore_till_sync();
+ /* Unset suspend reading from frontend flag */
+ pool_unset_suspend_reading_from_frontend();
+
/* Initialize where to send map for PREPARE statements */
#ifdef NOT_USED
memset(&session_context->prep_where, 0, sizeof(session_context->prep_where));
return 0;
}
+/*
+ * Is suspend_reading_from_frontend flag set?
+ */
+bool
+pool_is_suspend_reading_from_frontend(void)
+{
+ return session_context->suspend_reading_from_frontend;
+}
+
+/*
+ * Set suspend_reading_from_frontend flag.
+ */
+void
+pool_set_suspend_reading_from_frontend(void)
+{
+ session_context->suspend_reading_from_frontend = true;
+}
+
+/*
+ * Unset suspend_reading_from_frontend flag.
+ */
+void
+pool_unset_suspend_reading_from_frontend(void)
+{
+ session_context->suspend_reading_from_frontend = false;
+}
+
#ifdef NOT_USED
/*
* Set preferred "master" node id.
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2018 PgPool Global Development Group
+ * Copyright (c) 2003-2019 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
int major;
/* Protocol minor version number */
int minor;
+
+ /*
+ * Do not read messages from frontend. Used in extended protocol +
+ * streaming replication. If sync message is received from frontend, this
+ * flag prevent from reading any message from frontend until read for
+ * query message arrives from backend.
+ */
+ bool suspend_reading_from_frontend;
+
#ifdef NOT_USED
/* Preferred "master" node id. Only used for SimpleForwardToFrontend. */
int preferred_master_node_id;
extern void pool_set_major_version(int major);
extern void pool_set_minor_version(int minor);
extern int pool_get_minor_version(void);
+extern bool pool_is_suspend_reading_from_frontend(void);
+extern void pool_set_suspend_reading_from_frontend(void);
+extern void pool_unset_suspend_reading_from_frontend(void);
+
#ifdef NOT_USED
extern void pool_set_preferred_master_node_id(int node_id);
extern int pool_get_preferred_master_node_id(void);
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2018 PgPool Global Development Group
+ * Copyright (c) 2003-2019 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
static char *flatten_set_variable_args(const char *name, List *args);
static bool
process_pg_terminate_backend_func(POOL_QUERY_CONTEXT * query_context);
-static void pool_wait_till_ready_for_query(POOL_CONNECTION_POOL * backend);
static void pool_discard_except_sync_and_ready_for_query(POOL_CONNECTION * frontend,
POOL_CONNECTION_POOL * backend);
if (pool_read_buffer_is_empty(frontend) && frontend->no_forward != 0)
return POOL_CONTINUE;
+ /* Are we suspending reading from frontend? */
+ if (pool_is_suspend_reading_from_frontend())
+ return POOL_CONTINUE;
+
pool_read(frontend, &fkind, 1);
ereport(DEBUG5,
if (SL_MODE)
{
- /* Wait till Ready for query received */
- pool_wait_till_ready_for_query(backend);
+ /*
+ * From now on suspend to read from frontend until we receive
+ * ready for query message from backend.
+ */
+ pool_set_suspend_reading_from_frontend();
}
break;
ereport(DEBUG5,
(errmsg("processing backend response"),
errdetail("Ready For Query received")));
+ pool_unset_suspend_reading_from_frontend();
status = ReadyForQuery(frontend, backend, true, true);
#ifdef DEBUG
extern bool stop_now;
{
pool_set_ignore_till_sync();
pool_unset_query_in_progress();
+ pool_unset_suspend_reading_from_frontend();
if (SL_MODE)
pool_discard_except_sync_and_ready_for_query(frontend, backend);
}
return buf.data;
}
+#ifdef NOT_USED
/* Called when sync message is received.
* Wait till ready for query received.
*/
}
}
}
+#endif
/*
* Called when error response received in streaming replication mode and doing