Skip to content

Commit ace86a2

Browse files
sciascidNirbhay Choubey
authored andcommitted
- 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.
1 parent c1ea057 commit ace86a2

File tree

8 files changed

+77
-7
lines changed

8 files changed

+77
-7
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
2+
INSERT INTO t1 VALUES (DEFAULT);
3+
SET GLOBAL query_cache_size=1355776;
4+
SET SESSION wsrep_sync_wait = 7;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--query_cache_type=1
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--source include/galera_cluster.inc
2+
--source include/have_innodb.inc
3+
--source include/have_query_cache.inc
4+
5+
CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
6+
INSERT INTO t1 VALUES (DEFAULT);
7+
8+
--connection node_2
9+
--let $qcache_size_orig = `SELECT @@GLOBAL.query_cache_size`
10+
SET GLOBAL query_cache_size=1355776;
11+
SET SESSION wsrep_sync_wait = 7;
12+
13+
--disable_query_log
14+
15+
--let $count = 10000
16+
while ($count)
17+
{
18+
--connection node_1
19+
INSERT INTO t1 VALUES (DEFAULT);
20+
--let $val1 = `SELECT LAST_INSERT_ID()`
21+
--connection node_2
22+
--let $val2 = `SELECT MAX(id) FROM t1`
23+
--let $val3 = `SELECT $val1 != $val2`
24+
if ($val3)
25+
{
26+
--echo $val1 $val2
27+
--die wsrep_sync_wait failed
28+
}
29+
--dec $count
30+
}
31+
32+
--eval SET GLOBAL query_cache_size = $qcache_size_orig
33+
DROP TABLE t1;

sql/sql_cache.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,6 +1846,7 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
18461846
goto err;
18471847
}
18481848
}
1849+
18491850
/*
18501851
Try to obtain an exclusive lock on the query cache. If the cache is
18511852
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",
19571958
}
19581959
DBUG_PRINT("qcache", ("Query in query hash 0x%lx", (ulong)query_block));
19591960

1961+
#ifdef WITH_WSREP
1962+
if (WSREP_CLIENT(thd) && wsrep_must_sync_wait(thd)) {
1963+
unlock();
1964+
if (wsrep_sync_wait(thd))
1965+
goto err;
1966+
if (try_lock(TRUE))
1967+
goto err;
1968+
query_block = (Query_cache_block *) my_hash_search(&queries,
1969+
(uchar*) sql,
1970+
tot_length);
1971+
if (query_block == 0 ||
1972+
query_block->query()->result() == 0 ||
1973+
query_block->query()->result()->type != Query_cache_block::RESULT)
1974+
{
1975+
goto err_unlock;
1976+
}
1977+
}
1978+
#endif /* WITH_WSREP */
1979+
19601980
/* Now lock and test that nothing changed while blocks was unlocked */
19611981
BLOCK_LOCK_RD(query_block);
19621982

sql/sql_class.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,7 @@ THD::THD()
12131213
wsrep_mysql_replicated = 0;
12141214
wsrep_TOI_pre_query = NULL;
12151215
wsrep_TOI_pre_query_len = 0;
1216+
wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED;
12161217
#endif
12171218
/* Call to init() below requires fully initialized Open_tables_state. */
12181219
reset_open_tables_state(this);
@@ -1628,6 +1629,7 @@ void THD::init(void)
16281629
wsrep_mysql_replicated = 0;
16291630
wsrep_TOI_pre_query = NULL;
16301631
wsrep_TOI_pre_query_len = 0;
1632+
wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED;
16311633

16321634
/*
16331635
@@wsrep_causal_reads is now being handled via wsrep_sync_wait, update it
@@ -2361,6 +2363,10 @@ void THD::cleanup_after_query()
23612363
rgi_slave->cleanup_after_query();
23622364
#endif
23632365

2366+
#ifdef WITH_WSREP
2367+
wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED;
2368+
#endif /* WITH_WSREP */
2369+
23642370
DBUG_VOID_RETURN;
23652371
}
23662372

sql/sql_class.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2787,7 +2787,6 @@ class THD :public Statement,
27872787
query_id_t first_query_id;
27882788
} binlog_evt_union;
27892789

2790-
27912790
/**
27922791
Internal parser state.
27932792
Note that since the parser is not re-entrant, we keep only one parser
@@ -3865,6 +3864,7 @@ class THD :public Statement,
38653864
void* wsrep_apply_format;
38663865
bool wsrep_apply_toi; /* applier processing in TOI */
38673866
bool wsrep_skip_append_keys;
3867+
wsrep_gtid_t wsrep_sync_wait_gtid;
38683868
#endif /* WITH_WSREP */
38693869
};
38703870

sql/wsrep_mysqld.cc

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -810,19 +810,24 @@ bool wsrep_start_replication()
810810
return true;
811811
}
812812

813+
bool wsrep_must_sync_wait (THD* thd, uint mask)
814+
{
815+
return (thd->variables.wsrep_sync_wait & mask) &&
816+
thd->variables.wsrep_on &&
817+
!thd->in_active_multi_stmt_transaction() &&
818+
thd->wsrep_conflict_state != REPLAYING &&
819+
thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED;
820+
}
821+
813822
bool wsrep_sync_wait (THD* thd, uint mask)
814823
{
815-
if ((thd->variables.wsrep_sync_wait & mask) &&
816-
thd->variables.wsrep_on &&
817-
!thd->in_active_multi_stmt_transaction() &&
818-
thd->wsrep_conflict_state != REPLAYING)
824+
if (wsrep_must_sync_wait(thd, mask))
819825
{
820826
WSREP_DEBUG("wsrep_sync_wait: thd->variables.wsrep_sync_wait = %u, mask = %u",
821827
thd->variables.wsrep_sync_wait, mask);
822828
// This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0
823829
// TODO: modify to check if thd has locked any rows.
824-
wsrep_gtid_t gtid;
825-
wsrep_status_t ret= wsrep->causal_read (wsrep, &gtid);
830+
wsrep_status_t ret= wsrep->causal_read (wsrep, &thd->wsrep_sync_wait_gtid);
826831

827832
if (unlikely(WSREP_OK != ret))
828833
{

sql/wsrep_mysqld.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ extern void wsrep_kill_mysql(THD *thd);
192192
/* new defines */
193193
extern void wsrep_stop_replication(THD *thd);
194194
extern bool wsrep_start_replication();
195+
extern bool wsrep_must_sync_wait (THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ);
195196
extern bool wsrep_sync_wait (THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ);
196197
extern int wsrep_check_opts (int argc, char* const* argv);
197198
extern void wsrep_prepend_PATH (const char* path);

0 commit comments

Comments
 (0)