1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00
- 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.
This commit is contained in:
Daniele Sciascia
2015-10-20 17:54:14 +02:00
committed by Nirbhay Choubey
parent c1ea0570af
commit ace86a2375
8 changed files with 77 additions and 7 deletions

View File

@ -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;

View File

@ -0,0 +1 @@
--query_cache_type=1

View File

@ -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;

View File

@ -1846,6 +1846,7 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
goto err; goto err;
} }
} }
/* /*
Try to obtain an exclusive lock on the query cache. If the cache is 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 disabled or if a full cache flush is in progress, the attempt to
@ -1957,6 +1958,25 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
} }
DBUG_PRINT("qcache", ("Query in query hash 0x%lx", (ulong)query_block)); 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 */ /* Now lock and test that nothing changed while blocks was unlocked */
BLOCK_LOCK_RD(query_block); BLOCK_LOCK_RD(query_block);

View File

@ -1213,6 +1213,7 @@ THD::THD()
wsrep_mysql_replicated = 0; wsrep_mysql_replicated = 0;
wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query = NULL;
wsrep_TOI_pre_query_len = 0; wsrep_TOI_pre_query_len = 0;
wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED;
#endif #endif
/* Call to init() below requires fully initialized Open_tables_state. */ /* Call to init() below requires fully initialized Open_tables_state. */
reset_open_tables_state(this); reset_open_tables_state(this);
@ -1628,6 +1629,7 @@ void THD::init(void)
wsrep_mysql_replicated = 0; wsrep_mysql_replicated = 0;
wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query = NULL;
wsrep_TOI_pre_query_len = 0; 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 @@wsrep_causal_reads is now being handled via wsrep_sync_wait, update it
@ -2361,6 +2363,10 @@ void THD::cleanup_after_query()
rgi_slave->cleanup_after_query(); rgi_slave->cleanup_after_query();
#endif #endif
#ifdef WITH_WSREP
wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED;
#endif /* WITH_WSREP */
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }

View File

@ -2787,7 +2787,6 @@ public:
query_id_t first_query_id; query_id_t first_query_id;
} binlog_evt_union; } binlog_evt_union;
/** /**
Internal parser state. Internal parser state.
Note that since the parser is not re-entrant, we keep only one parser Note that since the parser is not re-entrant, we keep only one parser
@ -3865,6 +3864,7 @@ public:
void* wsrep_apply_format; void* wsrep_apply_format;
bool wsrep_apply_toi; /* applier processing in TOI */ bool wsrep_apply_toi; /* applier processing in TOI */
bool wsrep_skip_append_keys; bool wsrep_skip_append_keys;
wsrep_gtid_t wsrep_sync_wait_gtid;
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
}; };

View File

@ -810,19 +810,24 @@ bool wsrep_start_replication()
return true; 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) bool wsrep_sync_wait (THD* thd, uint mask)
{ {
if ((thd->variables.wsrep_sync_wait & mask) && if (wsrep_must_sync_wait(thd, mask))
thd->variables.wsrep_on &&
!thd->in_active_multi_stmt_transaction() &&
thd->wsrep_conflict_state != REPLAYING)
{ {
WSREP_DEBUG("wsrep_sync_wait: thd->variables.wsrep_sync_wait = %u, mask = %u", WSREP_DEBUG("wsrep_sync_wait: thd->variables.wsrep_sync_wait = %u, mask = %u",
thd->variables.wsrep_sync_wait, mask); thd->variables.wsrep_sync_wait, mask);
// This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0 // This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0
// TODO: modify to check if thd has locked any rows. // TODO: modify to check if thd has locked any rows.
wsrep_gtid_t gtid; wsrep_status_t ret= wsrep->causal_read (wsrep, &thd->wsrep_sync_wait_gtid);
wsrep_status_t ret= wsrep->causal_read (wsrep, &gtid);
if (unlikely(WSREP_OK != ret)) if (unlikely(WSREP_OK != ret))
{ {

View File

@ -192,6 +192,7 @@ extern void wsrep_kill_mysql(THD *thd);
/* new defines */ /* new defines */
extern void wsrep_stop_replication(THD *thd); extern void wsrep_stop_replication(THD *thd);
extern bool wsrep_start_replication(); 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 bool wsrep_sync_wait (THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ);
extern int wsrep_check_opts (int argc, char* const* argv); extern int wsrep_check_opts (int argc, char* const* argv);
extern void wsrep_prepend_PATH (const char* path); extern void wsrep_prepend_PATH (const char* path);