diff options
author | Daniele Sciascia <daniele.sciascia@galeracluster.com> | 2015-10-20 17:54:14 +0200 |
---|---|---|
committer | Nirbhay Choubey <nirbhay@mariadb.com> | 2016-02-09 21:28:54 -0500 |
commit | 8a71fde01f153bda42d57587527376bc33e9e3e9 (patch) | |
tree | 3d92424f21828d4e796e7ba65033fa96a6ecff50 | |
parent | 70113ee170cbace52d01afdb3ddd4ea5bfa92ebd (diff) | |
download | mariadb-git-8a71fde01f153bda42d57587527376bc33e9e3e9.tar.gz |
refs codership/mysql-wsrep#201
- Fixes query cache so that it is aware of wsrep_sync_wait.
Query cache would return (possibly stale) results to the
client, regardless of the value of wsrep_sync_wait.
- Includes the test case that reproduced the issue.
-rw-r--r-- | mysql-test/suite/galera/r/mysql-wsrep#201.result | 4 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/mysql-wsrep#201-master.opt | 1 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/mysql-wsrep#201.test | 33 | ||||
-rw-r--r-- | sql/sql_cache.cc | 20 | ||||
-rw-r--r-- | sql/sql_class.cc | 6 | ||||
-rw-r--r-- | sql/sql_class.h | 1 | ||||
-rw-r--r-- | sql/wsrep_mysqld.cc | 17 | ||||
-rw-r--r-- | sql/wsrep_mysqld.h | 1 |
8 files changed, 77 insertions, 6 deletions
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#201.result b/mysql-test/suite/galera/r/mysql-wsrep#201.result new file mode 100644 index 00000000000..1c0998e35ac --- /dev/null +++ b/mysql-test/suite/galera/r/mysql-wsrep#201.result @@ -0,0 +1,4 @@ +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (DEFAULT); +SET GLOBAL query_cache_size=1355776; +SET SESSION wsrep_sync_wait = 7; diff --git a/mysql-test/suite/galera/t/mysql-wsrep#201-master.opt b/mysql-test/suite/galera/t/mysql-wsrep#201-master.opt new file mode 100644 index 00000000000..a00258bc48c --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep#201-master.opt @@ -0,0 +1 @@ +--query_cache_type=1 diff --git a/mysql-test/suite/galera/t/mysql-wsrep#201.test b/mysql-test/suite/galera/t/mysql-wsrep#201.test new file mode 100644 index 00000000000..cc842afb6d0 --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep#201.test @@ -0,0 +1,33 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_query_cache.inc + +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (DEFAULT); + +--connection node_2 +--let $qcache_size_orig = `SELECT @@GLOBAL.query_cache_size` +SET GLOBAL query_cache_size=1355776; +SET SESSION wsrep_sync_wait = 7; + +--disable_query_log + +--let $count = 10000 +while ($count) +{ + --connection node_1 + INSERT INTO t1 VALUES (DEFAULT); + --let $val1 = `SELECT LAST_INSERT_ID()` + --connection node_2 + --let $val2 = `SELECT MAX(id) FROM t1` + --let $val3 = `SELECT $val1 != $val2` + if ($val3) + { + --echo $val1 $val2 + --die wsrep_sync_wait failed + } + --dec $count +} + +--eval SET GLOBAL query_cache_size = $qcache_size_orig +DROP TABLE t1; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index ad0472cfc2c..557d16d1312 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1804,6 +1804,7 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length) goto err; } } + /* Try to obtain an exclusive lock on the query cache. If the cache is disabled or if a full cache flush is in progress, the attempt to @@ -1915,6 +1916,25 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", } DBUG_PRINT("qcache", ("Query in query hash 0x%lx", (ulong)query_block)); +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_must_sync_wait(thd)) { + unlock(); + if (wsrep_sync_wait(thd)) + goto err; + if (try_lock(TRUE)) + goto err; + query_block = (Query_cache_block *) my_hash_search(&queries, + (uchar*) sql, + tot_length); + if (query_block == 0 || + query_block->query()->result() == 0 || + query_block->query()->result()->type != Query_cache_block::RESULT) + { + goto err_unlock; + } + } +#endif /* WITH_WSREP */ + /* Now lock and test that nothing changed while blocks was unlocked */ BLOCK_LOCK_RD(query_block); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index e13cee8de4a..09533599ac0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1118,6 +1118,7 @@ THD::THD() wsrep_bf_thd = NULL; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; + wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED; #endif /* Call to init() below requires fully initialized Open_tables_state. */ reset_open_tables_state(this); @@ -1487,6 +1488,7 @@ void THD::init(void) wsrep_bf_thd = NULL; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; + wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED; /* @@wsrep_causal_reads is now being handled via wsrep_sync_wait, update it @@ -2137,6 +2139,10 @@ void THD::cleanup_after_query() rli_slave->cleanup_after_query(); #endif +#ifdef WITH_WSREP + wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED; +#endif /* WITH_WSREP */ + DBUG_VOID_RETURN; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 6deabb04f3d..6e80eeb7096 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2395,6 +2395,7 @@ public: size_t wsrep_TOI_pre_query_len; void* wsrep_apply_format; bool wsrep_apply_toi; /* applier processing in TOI */ + wsrep_gtid_t wsrep_sync_wait_gtid; #endif /* WITH_WSREP */ /** Internal parser state. diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index c570c7b831d..71cff536b72 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -866,19 +866,24 @@ bool wsrep_start_replication() return true; } +bool wsrep_must_sync_wait (THD* thd, uint mask) +{ + return (thd->variables.wsrep_sync_wait & mask) && + thd->variables.wsrep_on && + !thd->in_active_multi_stmt_transaction() && + thd->wsrep_conflict_state != REPLAYING && + thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED; +} + bool wsrep_sync_wait (THD* thd, uint mask) { - if ((thd->variables.wsrep_sync_wait & mask) && - thd->variables.wsrep_on && - !thd->in_active_multi_stmt_transaction() && - thd->wsrep_conflict_state != REPLAYING) + if (wsrep_must_sync_wait(thd, mask)) { WSREP_DEBUG("wsrep_sync_wait: thd->variables.wsrep_sync_wait = %u, mask = %u", thd->variables.wsrep_sync_wait, mask); // This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0 // TODO: modify to check if thd has locked any rows. - wsrep_gtid_t gtid; - wsrep_status_t ret= wsrep->causal_read (wsrep, >id); + wsrep_status_t ret= wsrep->causal_read (wsrep, &thd->wsrep_sync_wait_gtid); if (unlikely(WSREP_OK != ret)) { diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index e6fe0c04fac..f109211751d 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -183,6 +183,7 @@ extern void wsrep_kill_mysql(THD *thd); /* new defines */ extern void wsrep_stop_replication(THD *thd); extern bool wsrep_start_replication(); +extern bool wsrep_must_sync_wait (THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ); extern bool wsrep_sync_wait (THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ); extern int wsrep_check_opts (int argc, char* const* argv); extern void wsrep_prepend_PATH (const char* path); |