Fix query cache bug reported in pgpool-general-jp:1441.
authorTatsuo Ishii <ishii@postgresql.org>
Wed, 18 Jan 2017 23:24:34 +0000 (08:24 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Wed, 18 Jan 2017 23:38:33 +0000 (08:38 +0900)
In streaming replication mode with query cache enabled, SELECT hangs
in the following scenario:

1) a SELECT hits query cache and returns rows from the query cache.
2) following SELECT needs to search meta data and it hangs.

In #1, while returning the cached result, it misses to call
pool_unset_pending_response(), which leave the pending_response flag
be set. In #2, do_query() checks the flag and tries to read pending
response from backend. Since there's no pending data in backend, it
hangs in reading data from backend.

Fix is, just call pool_unset_pending_response() in #1 to reset the
flag.

Bug report and fix provided by Nobuyuki Nagai.

New regression test item (068) added by me.

src/protocol/pool_proto_modules.c
src/test/regression/tests/068.memqcache_bug/Sample.java [new file with mode: 0644]
src/test/regression/tests/068.memqcache_bug/test.sh [new file with mode: 0755]

index d9bbca41fe913331fcc92993277c32d1421585a2..9d05d82e771f0c692bebd45186506e334450f974 100644 (file)
@@ -814,6 +814,7 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
                        pool_set_skip_reading_from_backends();
                        pool_stats_count_up_num_cache_hits();
                        pool_unset_query_in_progress();
+                       pool_unset_pending_response();
                        return POOL_CONTINUE;
                }
        }
diff --git a/src/test/regression/tests/068.memqcache_bug/Sample.java b/src/test/regression/tests/068.memqcache_bug/Sample.java
new file mode 100644 (file)
index 0000000..a73154b
--- /dev/null
@@ -0,0 +1,50 @@
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.Properties;
+
+import org.postgresql.Driver;
+
+public class Sample {
+    public Sample() {
+    }
+
+    public static void main(String[] args) throws Exception {
+        ResultSet rs;
+        Properties props = new Properties();
+        props.setProperty("user", "t-ishii");
+        props.setProperty("password", "");
+        props.setProperty("protocolVersion", "3");
+        DriverManager.setLogWriter(new PrintWriter(System.out));
+        Driver.setLogLevel(2);
+        Connection conn = DriverManager.getConnection(
+                "jdbc:postgresql://localhost:11000/test", props);
+        conn.setAutoCommit(true);
+        Statement st = conn.createStatement();
+        st.setFetchSize(100);
+       // Does not hit cache
+        rs = st.executeQuery("SELECT 1");
+        while (rs.next()) {
+            System.out.println(rs.getString(1));
+        }
+        rs.close();
+
+       // Does hit cache
+        rs = st.executeQuery("SELECT 1");
+        while (rs.next()) {
+            System.out.println(rs.getString(1));
+        }
+        rs.close();
+
+       // To call do_query()
+        rs = st.executeQuery("SELECT * FROM t1");
+        while (rs.next()) {
+            System.out.println(rs.getString(1));
+        }
+        rs.close();
+
+       conn.close();
+    }
+}
diff --git a/src/test/regression/tests/068.memqcache_bug/test.sh b/src/test/regression/tests/068.memqcache_bug/test.sh
new file mode 100755 (executable)
index 0000000..273075c
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+#-------------------------------------------------------------------
+# test script for a memqcache bug reported in pgpool-general-jp:1441.
+# (do_query() hangs in certain condition)
+# requires Java PostgreSQL JDBC driver.
+
+source $TESTLIBS
+TESTDIR=testdir
+export CLASSPATH=.:/usr/local/pgsql/share/postgresql-9.2-1003.jdbc4.jar
+
+rm -fr $TESTDIR
+mkdir $TESTDIR
+cd $TESTDIR
+
+# create test environment
+echo -n "creating test environment..."
+$PGPOOL_SETUP -m s -n 2 || exit 1
+echo "done."
+
+source ./bashrc.ports
+
+export PGPORT=$PGPOOL_PORT
+
+echo "memory_cache_enabled = on" >> etc/pgpool.conf
+sh startall
+wait_for_pgpool_startup
+
+cd ..
+psql test <<EOF
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(i int);
+EOF
+javac Sample.java
+java Sample    # hang here if the bug bites you...
+cd $TESTDIR
+sh shutdownall
+exit 0
+