From 7398ae009177cdc67c29f055a4eedec4adce8a79 Mon Sep 17 00:00:00 2001 From: Tatsuo Ishii Date: Mon, 5 Nov 2018 21:14:58 +0900 Subject: [PATCH] Fix query cache invalidation bug. When a DML is executed in an explicit transaction, the table oid buffer is wiped out by pool_reset_memqcache_buffer() and query cache is not invalidated at the commit time because there's no DML oid exists to invalidate query cache any more. To fix this, add new bool parameter to pool_reset_memqcache_buffer() to specify whether to reset table oid buffer or not. When a DML is executed in an explicit transaction, call pool_reset_memqcache_buffer(false) to preserve the table oid buffer. Issue reported at https://github.com/pgpool/pgpool2/issues/19. --- src/query_cache/pool_memqcache.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/query_cache/pool_memqcache.c b/src/query_cache/pool_memqcache.c index d73d98ab7..a96c90657 100644 --- a/src/query_cache/pool_memqcache.c +++ b/src/query_cache/pool_memqcache.c @@ -77,7 +77,7 @@ static void pool_discard_dml_table_oid(void); static void pool_invalidate_query_cache(int num_table_oids, int *table_oid, bool unlink, int dboid); static int pool_get_database_oid(void); static void pool_add_table_oid_map(POOL_CACHEKEY * cachkey, int num_table_oids, int *table_oids); -static void pool_reset_memqcache_buffer(void); +static void pool_reset_memqcache_buffer(bool reset_dml_oids); static POOL_CACHEID * pool_add_item_shmem_cache(POOL_QUERY_HASH * query_hash, char *data, int size); static POOL_CACHEID * pool_find_item_on_shmem_cache(POOL_QUERY_HASH * query_hash); static char *pool_get_item_shmem_cache(POOL_QUERY_HASH * query_hash, int *size, int *sts); @@ -1698,10 +1698,11 @@ pool_invalidate_query_cache(int num_table_oids, int *table_oid, bool unlinkp, in } /* - * Reset SELECT data buffers + * Reset SELECT data buffers. If reset_dml_oids is true, call + * pool_discard_dml_table_oid() to reset table oids used in DML statements. */ static void -pool_reset_memqcache_buffer(void) +pool_reset_memqcache_buffer(bool reset_dml_oids) { POOL_SESSION_CONTEXT *session_context; @@ -1744,7 +1745,10 @@ pool_reset_memqcache_buffer(void) session_context->query_context->temp_cache = NULL; } } - pool_discard_dml_table_oid(); + + if (reset_dml_oids) + pool_discard_dml_table_oid(); + pool_tmp_stats_reset_num_selects(); } @@ -3280,7 +3284,7 @@ pool_handle_query_cache(POOL_CONNECTION_POOL * backend, char *query, Node *node, pool_stats_count_up_num_selects(1); /* Reset temp buffer */ - pool_reset_memqcache_buffer(); + pool_reset_memqcache_buffer(true); } else { @@ -3334,7 +3338,7 @@ pool_handle_query_cache(POOL_CONNECTION_POOL * backend, char *query, Node *node, else if (is_rollback_query(node)) /* Rollback? */ { /* Discard buffered data */ - pool_reset_memqcache_buffer(); + pool_reset_memqcache_buffer(true); } else if (is_commit_query(node)) /* Commit? */ { @@ -3386,7 +3390,7 @@ pool_handle_query_cache(POOL_CONNECTION_POOL * backend, char *query, Node *node, /* Count up number of SELECT stats */ pool_stats_count_up_num_selects(pool_tmp_stats_get_num_selects()); - pool_reset_memqcache_buffer(); + pool_reset_memqcache_buffer(true); } else /* Non cache safe queries */ { @@ -3397,7 +3401,7 @@ pool_handle_query_cache(POOL_CONNECTION_POOL * backend, char *query, Node *node, { /* Count up SELECT stats */ pool_stats_count_up_num_selects(1); - pool_reset_memqcache_buffer(); + pool_reset_memqcache_buffer(true); } else { @@ -3422,7 +3426,7 @@ pool_handle_query_cache(POOL_CONNECTION_POOL * backend, char *query, Node *node, pool_invalidate_query_cache(num_oids, oids, true, dboid); pool_discard_oid_maps_by_db(dboid); pool_shmem_unlock(); - pool_reset_memqcache_buffer(); + pool_reset_memqcache_buffer(true); pfree(oids); ereport(DEBUG2, @@ -3451,7 +3455,7 @@ pool_handle_query_cache(POOL_CONNECTION_POOL * backend, char *query, Node *node, pool_invalidate_query_cache(num_oids, oids, true, 0); pool_shmem_unlock(); POOL_SETMASK(&oldmask); - pool_reset_memqcache_buffer(); + pool_reset_memqcache_buffer(true); } else { @@ -3461,7 +3465,7 @@ pool_handle_query_cache(POOL_CONNECTION_POOL * backend, char *query, Node *node, * DML/DDL modifies the TABLE which SELECT uses. */ pool_check_and_discard_cache_buffer(num_oids, oids); - pool_reset_memqcache_buffer(); + pool_reset_memqcache_buffer(false); } } else if (num_oids == 0) @@ -3470,7 +3474,7 @@ pool_handle_query_cache(POOL_CONNECTION_POOL * backend, char *query, Node *node, * It is also necessary to clear cache buffers in case of no * oid queries (like BEGIN, CHECKPOINT, VACUUM, etc) too. */ - pool_reset_memqcache_buffer(); + pool_reset_memqcache_buffer(true); } } } -- 2.39.5