Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
sciascid authored and Nirbhay Choubey committed Feb 22, 2016
1 parent c1ea057 commit ace86a2
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 7 deletions.
4 changes: 4 additions & 0 deletions mysql-test/suite/galera/r/mysql-wsrep#201.result
Original file line number Diff line number Diff line change
@@ -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;
1 change: 1 addition & 0 deletions mysql-test/suite/galera/t/mysql-wsrep#201-master.opt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--query_cache_type=1
33 changes: 33 additions & 0 deletions mysql-test/suite/galera/t/mysql-wsrep#201.test
Original file line number Diff line number Diff line change
@@ -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;
20 changes: 20 additions & 0 deletions sql/sql_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1846,6 +1846,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
Expand Down Expand Up @@ -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));

#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);

Expand Down
6 changes: 6 additions & 0 deletions sql/sql_class.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,7 @@ THD::THD()
wsrep_mysql_replicated = 0;
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);
Expand Down Expand Up @@ -1628,6 +1629,7 @@ void THD::init(void)
wsrep_mysql_replicated = 0;
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
Expand Down Expand Up @@ -2361,6 +2363,10 @@ void THD::cleanup_after_query()
rgi_slave->cleanup_after_query();
#endif

#ifdef WITH_WSREP
wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED;
#endif /* WITH_WSREP */

DBUG_VOID_RETURN;
}

Expand Down
2 changes: 1 addition & 1 deletion sql/sql_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -2787,7 +2787,6 @@ class THD :public Statement,
query_id_t first_query_id;
} binlog_evt_union;


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

Expand Down
17 changes: 11 additions & 6 deletions sql/wsrep_mysqld.cc
Original file line number Diff line number Diff line change
Expand Up @@ -810,19 +810,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, &gtid);
wsrep_status_t ret= wsrep->causal_read (wsrep, &thd->wsrep_sync_wait_gtid);

if (unlikely(WSREP_OK != ret))
{
Expand Down
1 change: 1 addition & 0 deletions sql/wsrep_mysqld.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,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);
Expand Down

0 comments on commit ace86a2

Please sign in to comment.