Don't ignore sync message from frontend when query cache is enabled.
authorTatsuo Ishii <ishii@postgresql.org>
Mon, 5 Sep 2016 23:08:32 +0000 (08:08 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Mon, 5 Sep 2016 23:09:42 +0000 (08:09 +0900)
While returning cached query result, sync message sent from frontend
is discarded. This is harmless because "ready for query" messages is
sent to frontend afterward. Problem is, AccessShareLock held by
previous parse message processing is not released until sync message
is received by the backend. Fix is, forwarding the sync message to
backend and discarding "ready for query" message returned from
backend.

Per [pgpool-hackers: 1787].

pool_memqcache.c

index 54857429c76b199a4f1cc698e886a350080dd4e4..13580da5f7c09749dffd6ec92b65d1d99587c67a 100644 (file)
@@ -3,7 +3,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2014     PgPool Global Development Group
+ * Copyright (c) 2003-2016     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -582,14 +582,17 @@ POOL_STATUS pool_fetch_from_memory_cache(POOL_CONNECTION *frontend,
                free(qcache);
 
                /*
-                * If we are doing extended query, wait and discard Sync
-                * message from frontend. This is necessary to prevent
-                * receiving Sync message after Sending Ready for query.
+                * If we are doing extended query, forward sync message from frontend to
+                * backend. This is necessary to prevent receiving Sync message after
+                * Sending Ready for query.
                 */
                if (pool_is_doing_extended_query_message())
                {
                        char kind;
                        int32 len;
+                       POOL_SESSION_CONTEXT *session_context;
+                       POOL_CONNECTION *target_backend;
+                       char buf[5];
 
                        if (pool_flush(frontend))
                                return POOL_END;
@@ -598,6 +601,16 @@ POOL_STATUS pool_fetch_from_memory_cache(POOL_CONNECTION *frontend,
                        pool_debug("pool_fetch_from_memory_cache: expecting sync: %c", kind);
                        if (pool_read(frontend, &len, sizeof(len)))
                                return POOL_END;
+
+                       /* Forward "Sync" message to backend */
+                       session_context = pool_get_session_context(true);
+                       target_backend = CONNECTION(backend, session_context->load_balance_node_id);
+                       pool_write(target_backend, &kind, 1);
+                       pool_write_and_flush(target_backend, &len, sizeof(len));
+
+                       /* Read and discard "Ready for query" message from backend */
+                       pool_read(target_backend, &kind, 1);
+                       pool_read(target_backend, buf, sizeof(buf));
                }
 
                /*