From 8a71fde01f153bda42d57587527376bc33e9e3e9 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Tue, 20 Oct 2015 17:54:14 +0200 Subject: [PATCH 01/12] 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. --- .../suite/galera/r/mysql-wsrep#201.result | 4 +++ .../suite/galera/t/mysql-wsrep#201-master.opt | 1 + .../suite/galera/t/mysql-wsrep#201.test | 33 +++++++++++++++++++ sql/sql_cache.cc | 20 +++++++++++ sql/sql_class.cc | 6 ++++ sql/sql_class.h | 1 + sql/wsrep_mysqld.cc | 17 ++++++---- sql/wsrep_mysqld.h | 1 + 8 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/galera/r/mysql-wsrep#201.result create mode 100644 mysql-test/suite/galera/t/mysql-wsrep#201-master.opt create mode 100644 mysql-test/suite/galera/t/mysql-wsrep#201.test 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); From 0c7dffe9e18e249ca7930b29d7c3c6832c03a278 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Thu, 22 Oct 2015 17:30:20 +0200 Subject: [PATCH 02/12] refs codership/mysql-wsrep#201 - Eliminates code duplication in query cache patch - Reduces the number of iterations in mysql-wsrep#201.test to shorten the execution time - Adds a new test case that exercises more scenarios --- .../r/galera_query_cache_sync_wait.result | 45 ++++++++++ .../t/galera_query_cache_sync_wait-master.opt | 1 + .../t/galera_query_cache_sync_wait.test | 90 +++++++++++++++++++ .../suite/galera/t/mysql-wsrep#201.test | 2 +- sql/sql_cache.cc | 22 ++--- 5 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_query_cache_sync_wait.result create mode 100644 mysql-test/suite/galera/t/galera_query_cache_sync_wait-master.opt create mode 100644 mysql-test/suite/galera/t/galera_query_cache_sync_wait.test diff --git a/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result b/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result new file mode 100644 index 00000000000..e9faff8be8b --- /dev/null +++ b/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result @@ -0,0 +1,45 @@ +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT1S"; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +SET SESSION wsrep_sync_wait = 7; +SELECT MAX(id) FROM t1; +MAX(id) +1 +INSERT INTO t1 VALUES (2); +SELECT MAX(id) FROM t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +FLUSH QUERY CACHE; +SET SESSION wsrep_sync_wait = 7; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +INSERT INTO t1 VALUES (3); +SELECT MAX(id) FROM t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +INSERT INTO t1 VALUES (4); +SET SESSION wsrep_sync_wait = 7; +SELECT MAX(id) FROM t1; +MAX(id) +4 +SET SESSION wsrep_sync_wait = 7; +FLUSH STATUS; +SELECT MAX(id) FROM t1; +MAX(id) +4 +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +VARIABLE_VALUE = 1 +1 +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +INSERT INTO t1 VALUES (5); +SET SESSION wsrep_sync_wait = 7; +SELECT MAX(id) FROM t1 ; +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +MAX(id) +5 +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +VARIABLE_VALUE = 1 +1 diff --git a/mysql-test/suite/galera/t/galera_query_cache_sync_wait-master.opt b/mysql-test/suite/galera/t/galera_query_cache_sync_wait-master.opt new file mode 100644 index 00000000000..a00258bc48c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_query_cache_sync_wait-master.opt @@ -0,0 +1 @@ +--query_cache_type=1 diff --git a/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test b/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test new file mode 100644 index 00000000000..0634eba3264 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test @@ -0,0 +1,90 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/have_query_cache.inc + +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT1S"; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +SET SESSION wsrep_sync_wait = 7; +SELECT MAX(id) FROM t1; # first lookup miss + +# +# Query cache hit, wait timeout +# + +--connection node_1 +INSERT INTO t1 VALUES (2); + +--connection node_2 +--error ER_LOCK_WAIT_TIMEOUT +SELECT MAX(id) FROM t1; +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; + +FLUSH QUERY CACHE; +SET SESSION wsrep_sync_wait = 7; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; + +# +# Query cache miss, wait timeout +# + +--connection node_1 +INSERT INTO t1 VALUES (3); + +--connection node_2 +--error ER_LOCK_WAIT_TIMEOUT +SELECT MAX(id) FROM t1; +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; + +# +# Query cache miss +# + +--connection node_1 +INSERT INTO t1 VALUES (4); + +--connection node_2 +SET SESSION wsrep_sync_wait = 7; +SELECT MAX(id) FROM t1; +SET SESSION wsrep_sync_wait = 7; + +# +# Query cache hit +# + +FLUSH STATUS; +SELECT MAX(id) FROM t1; +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; + +# +# Query cache invalidated +# + +--connection node_1 +INSERT INTO t1 VALUES (5); + +--connection node_2 +SET SESSION wsrep_sync_wait = 7; +--send SELECT MAX(id) FROM t1 + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; + +--connection node_2 +--reap +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; + + +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = "$wsrep_provider_options_orig" +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/mysql-wsrep#201.test b/mysql-test/suite/galera/t/mysql-wsrep#201.test index cc842afb6d0..e9327540195 100644 --- a/mysql-test/suite/galera/t/mysql-wsrep#201.test +++ b/mysql-test/suite/galera/t/mysql-wsrep#201.test @@ -12,7 +12,7 @@ SET SESSION wsrep_sync_wait = 7; --disable_query_log ---let $count = 10000 +--let $count = 500 while ($count) { --connection node_1 diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 557d16d1312..32188a2a1fe 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1804,7 +1804,6 @@ 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 @@ -1904,6 +1903,13 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", (int)flags.autocommit)); memcpy((uchar *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)), (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE); + +#ifdef WITH_WSREP + bool once_more; + once_more= true; +lookup: +#endif /* WITH_WSREP */ + query_block = (Query_cache_block *) my_hash_search(&queries, (uchar*) sql, tot_length); /* Quick abort on unlocked data */ @@ -1917,21 +1923,15 @@ 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)) { + if (once_more && 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; - } + once_more= false; + goto lookup; } #endif /* WITH_WSREP */ From 484bbd332f0876cd7df30122bcb339b62a64c871 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Wed, 4 Nov 2015 09:36:01 +0100 Subject: [PATCH 03/12] refs codership/mysql-wsrep#201 Manually merged query cache fixes from 97c02faf0a39dd189eeda4f75fb35bc5db69d541. --- sql/log_event.cc | 20 +++++++++++++++++++- sql/sql_parse.cc | 6 ++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 5e9ee6136a9..a2fb263d2dd 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8556,7 +8556,18 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) const_cast(rli)->m_table_map.set_table(ptr->table_id, ptr->table); #ifdef HAVE_QUERY_CACHE - query_cache.invalidate_locked_for_write(thd, rli->tables_to_lock); +#ifdef WITH_WSREP + /* + Moved invalidation right before the call to rows_event_stmt_cleanup(), + to avoid query cache being polluted with stale entries. + */ + if (! (WSREP(thd) && (thd->wsrep_exec_mode == REPL_RECV))) + { +#endif /* WITH_WSREP */ + query_cache.invalidate_locked_for_write(thd, rli->tables_to_lock); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ #endif } @@ -8749,6 +8760,13 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) DBUG_RETURN(error); } +#if defined(WITH_WSREP) && defined(HAVE_QUERY_CACHE) + if (get_flags(STMT_END_F) && + WSREP(thd) && thd->wsrep_exec_mode == REPL_RECV) + { + query_cache.invalidate_locked_for_write(thd, rli->tables_to_lock); + } +#endif /* WITH_WSREP */ if (get_flags(STMT_END_F) && (error= rows_event_stmt_cleanup(rli, thd))) slave_rows_error_report(ERROR_LEVEL, thd->is_error() ? 0 : error, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index dc3c318f5e0..885a5a2f42a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6544,6 +6544,12 @@ void mysql_parse(THD *thd, char *rawbuf, uint length, thd->lex->sql_command= SQLCOM_SELECT; status_var_increment(thd->status_var.com_stat[SQLCOM_SELECT]); thd->update_stats(); +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd)) + { + thd->wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED; + } +#endif /* WITH_WSREP */ } DBUG_VOID_RETURN; } From 652e4c1d3333ef0649a504995e39b5c0c664c5ff Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 10 Feb 2016 17:29:28 -0500 Subject: [PATCH 04/12] Fix for a build failure. --- sql/sql_cache.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 32188a2a1fe..8794cdb2a45 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1928,7 +1928,7 @@ lookup: unlock(); if (wsrep_sync_wait(thd)) goto err; - if (try_lock(TRUE)) + if (try_lock(thd, Query_cache::TIMEOUT)) goto err; once_more= false; goto lookup; From 8a93a7c0b0436a1b863c3b3cc165dca9a690a064 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Wed, 4 Nov 2015 16:19:48 +0200 Subject: [PATCH 05/12] refs codership/mysql-wsrep#226 Limit binlog recovery to found wsrep position Limit binlog recovery so that the wsrep position found from storage engines is not exceeded. This is required to have consistent position between wsrep position stored in innodb header and recoverd binlog. --- sql/log.cc | 31 ++++++++++++++++++++++++++++++- sql/wsrep_mysqld.cc | 24 ++++++++++++++++++++++++ sql/wsrep_mysqld.h | 2 +- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index f9756e6c450..cf0c066c750 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -7701,6 +7701,22 @@ int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle) HASH xids; MEM_ROOT mem_root; +#ifdef WITH_WSREP + /* + Read current wsrep position from storage engines to have consistent + end position for binlog scan. + */ + wsrep_uuid_t uuid; + wsrep_seqno_t seqno; + wsrep_get_SE_checkpoint(uuid, seqno); + char uuid_str[40]; + wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str)); + WSREP_INFO("Binlog recovery, found wsrep position %s:%lld", uuid_str, + (long long)seqno); + const wsrep_seqno_t last_xid_seqno= seqno; + wsrep_seqno_t cur_xid_seqno= WSREP_SEQNO_UNDEFINED; +#endif /* WITH_WSREP */ + if (! fdle->is_valid() || my_hash_init(&xids, &my_charset_bin, TC_LOG_PAGE_SIZE/3, 0, sizeof(my_xid), 0, 0, MYF(0))) @@ -7712,7 +7728,12 @@ int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle) while ((ev= Log_event::read_log_event(log, 0, fdle, opt_master_verify_checksum)) - && ev->is_valid()) + && ev->is_valid() +#ifdef WITH_WSREP + && (last_xid_seqno == WSREP_SEQNO_UNDEFINED || + last_xid_seqno != cur_xid_seqno) +#endif + ) { if (ev->get_type_code() == XID_EVENT) { @@ -7721,10 +7742,18 @@ int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle) sizeof(xev->xid)); if (!x || my_hash_insert(&xids, x)) goto err2; +#ifdef WITH_WSREP + cur_xid_seqno= xev->xid; +#endif /* WITH_WSREP */ } delete ev; } +#ifdef WITH_WSREP + WSREP_INFO("Binlog recovery scan stopped at Xid event %lld", + (long long)cur_xid_seqno); +#endif /* WITH_WSREP */ + if (ha_recover(&xids)) goto err2; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 71cff536b72..48114fcba34 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -207,6 +207,30 @@ void wsrep_get_SE_checkpoint(XID* xid) plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, xid); } +void wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno) +{ + uuid= WSREP_UUID_UNDEFINED; + seqno= WSREP_SEQNO_UNDEFINED; + + XID xid; + memset(&xid, 0, sizeof(xid)); + xid.formatID= -1; + + wsrep_get_SE_checkpoint(&xid); + + if (xid.formatID == -1) return; // nil XID + + if (!wsrep_is_wsrep_xid(&xid)) + { + WSREP_WARN("Read non-wsrep XID from storage engines."); + return; + } + + uuid= *wsrep_xid_uuid(&xid); + seqno= wsrep_xid_seqno(&xid); +} + + static wsrep_cb_status_t wsrep_view_handler_cb (void* app_ctx, void* recv_ctx, diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index f109211751d..3fb5189937e 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -316,7 +316,7 @@ int wsrep_alter_event_query(THD *thd, uchar** buf, size_t* buf_len); const wsrep_uuid_t* wsrep_cluster_uuid(); struct xid_t; void wsrep_set_SE_checkpoint(xid_t*); - +void wsrep_get_SE_checkpoint(wsrep_uuid_t&, wsrep_seqno_t&); void wsrep_xid_init(xid_t*, const wsrep_uuid_t*, wsrep_seqno_t); const wsrep_uuid_t* wsrep_xid_uuid(const xid_t*); wsrep_seqno_t wsrep_xid_seqno(const xid_t*); From bd1d2b90a77f31c7d982f18902a39a2cadce0cc3 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Fri, 6 Nov 2015 10:50:21 +0100 Subject: [PATCH 06/12] refs codership/mysql-wsrep#201 Removes MTR tests. --- .../r/galera_query_cache_sync_wait.result | 45 ---------- .../suite/galera/r/mysql-wsrep#201.result | 4 - .../t/galera_query_cache_sync_wait-master.opt | 1 - .../t/galera_query_cache_sync_wait.test | 90 ------------------- .../suite/galera/t/mysql-wsrep#201-master.opt | 1 - .../suite/galera/t/mysql-wsrep#201.test | 33 ------- 6 files changed, 174 deletions(-) delete mode 100644 mysql-test/suite/galera/r/galera_query_cache_sync_wait.result delete mode 100644 mysql-test/suite/galera/r/mysql-wsrep#201.result delete mode 100644 mysql-test/suite/galera/t/galera_query_cache_sync_wait-master.opt delete mode 100644 mysql-test/suite/galera/t/galera_query_cache_sync_wait.test delete mode 100644 mysql-test/suite/galera/t/mysql-wsrep#201-master.opt delete mode 100644 mysql-test/suite/galera/t/mysql-wsrep#201.test diff --git a/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result b/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result deleted file mode 100644 index e9faff8be8b..00000000000 --- a/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result +++ /dev/null @@ -1,45 +0,0 @@ -CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1); -SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT1S"; -SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; -SET SESSION wsrep_sync_wait = 7; -SELECT MAX(id) FROM t1; -MAX(id) -1 -INSERT INTO t1 VALUES (2); -SELECT MAX(id) FROM t1; -ERROR HY000: Lock wait timeout exceeded; try restarting transaction -SET GLOBAL DEBUG = ""; -SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; -FLUSH QUERY CACHE; -SET SESSION wsrep_sync_wait = 7; -SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; -INSERT INTO t1 VALUES (3); -SELECT MAX(id) FROM t1; -ERROR HY000: Lock wait timeout exceeded; try restarting transaction -SET GLOBAL DEBUG = ""; -SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; -INSERT INTO t1 VALUES (4); -SET SESSION wsrep_sync_wait = 7; -SELECT MAX(id) FROM t1; -MAX(id) -4 -SET SESSION wsrep_sync_wait = 7; -FLUSH STATUS; -SELECT MAX(id) FROM t1; -MAX(id) -4 -SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; -VARIABLE_VALUE = 1 -1 -SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; -INSERT INTO t1 VALUES (5); -SET SESSION wsrep_sync_wait = 7; -SELECT MAX(id) FROM t1 ; -SET GLOBAL DEBUG = ""; -SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; -MAX(id) -5 -SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; -VARIABLE_VALUE = 1 -1 diff --git a/mysql-test/suite/galera/r/mysql-wsrep#201.result b/mysql-test/suite/galera/r/mysql-wsrep#201.result deleted file mode 100644 index 1c0998e35ac..00000000000 --- a/mysql-test/suite/galera/r/mysql-wsrep#201.result +++ /dev/null @@ -1,4 +0,0 @@ -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/galera_query_cache_sync_wait-master.opt b/mysql-test/suite/galera/t/galera_query_cache_sync_wait-master.opt deleted file mode 100644 index a00258bc48c..00000000000 --- a/mysql-test/suite/galera/t/galera_query_cache_sync_wait-master.opt +++ /dev/null @@ -1 +0,0 @@ ---query_cache_type=1 diff --git a/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test b/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test deleted file mode 100644 index 0634eba3264..00000000000 --- a/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test +++ /dev/null @@ -1,90 +0,0 @@ ---source include/galera_cluster.inc ---source include/have_innodb.inc ---source include/have_debug_sync.inc ---source include/have_query_cache.inc - -CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1); - ---connection node_2 ---let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` -SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT1S"; -SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; -SET SESSION wsrep_sync_wait = 7; -SELECT MAX(id) FROM t1; # first lookup miss - -# -# Query cache hit, wait timeout -# - ---connection node_1 -INSERT INTO t1 VALUES (2); - ---connection node_2 ---error ER_LOCK_WAIT_TIMEOUT -SELECT MAX(id) FROM t1; -SET GLOBAL DEBUG = ""; -SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; - -FLUSH QUERY CACHE; -SET SESSION wsrep_sync_wait = 7; -SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; - -# -# Query cache miss, wait timeout -# - ---connection node_1 -INSERT INTO t1 VALUES (3); - ---connection node_2 ---error ER_LOCK_WAIT_TIMEOUT -SELECT MAX(id) FROM t1; -SET GLOBAL DEBUG = ""; -SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; - -# -# Query cache miss -# - ---connection node_1 -INSERT INTO t1 VALUES (4); - ---connection node_2 -SET SESSION wsrep_sync_wait = 7; -SELECT MAX(id) FROM t1; -SET SESSION wsrep_sync_wait = 7; - -# -# Query cache hit -# - -FLUSH STATUS; -SELECT MAX(id) FROM t1; -SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; -SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; - -# -# Query cache invalidated -# - ---connection node_1 -INSERT INTO t1 VALUES (5); - ---connection node_2 -SET SESSION wsrep_sync_wait = 7; ---send SELECT MAX(id) FROM t1 - ---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 ---connection node_2a -SET GLOBAL DEBUG = ""; -SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; - ---connection node_2 ---reap -SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; - - ---disable_query_log ---eval SET GLOBAL wsrep_provider_options = "$wsrep_provider_options_orig" -DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/mysql-wsrep#201-master.opt b/mysql-test/suite/galera/t/mysql-wsrep#201-master.opt deleted file mode 100644 index a00258bc48c..00000000000 --- a/mysql-test/suite/galera/t/mysql-wsrep#201-master.opt +++ /dev/null @@ -1 +0,0 @@ ---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 deleted file mode 100644 index e9327540195..00000000000 --- a/mysql-test/suite/galera/t/mysql-wsrep#201.test +++ /dev/null @@ -1,33 +0,0 @@ ---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 = 500 -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; From 1ce821b509cdce915d8dd76b1e080bd26fa2a296 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Thu, 12 Nov 2015 10:33:04 +0200 Subject: [PATCH 07/12] Refs codership/mysql-wsrep#221 - disabling certain IB atomic builtins, which caused complete hangs --- storage/innobase/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index cc494a7cd7a..603455196fc 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -119,12 +119,16 @@ IF(NOT CMAKE_CROSSCOMPILING) ENDIF() IF(HAVE_IB_GCC_ATOMIC_BUILTINS) +IF(NOT WITH_WSREP) ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS=1) ENDIF() +ENDIF() IF(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) +IF(NOT WITH_WSREP) ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_TEST_AND_SET=1) ENDIF() +ENDIF() IF(HAVE_IB_GCC_SYNC_SYNCHRONISE) ADD_DEFINITIONS(-DHAVE_IB_GCC_SYNC_SYNCHRONISE=1) From 403a8bf8dfcf54bb24f7e376f43381c0d802810f Mon Sep 17 00:00:00 2001 From: Philip Stoev Date: Mon, 16 Nov 2015 04:07:08 -0800 Subject: [PATCH 08/12] Bump WSREP_PATCH_VERSION in cmake/wsrep.cmake to 13 --- cmake/wsrep.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 7740a4608f6..8c5d9ee5212 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -18,7 +18,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "12") +SET(WSREP_PATCH_VERSION "13") # MariaDB addition: Revision number of the last revision merged from # codership branch visible in @@visible_comment. From a6d0903764d316af98ec0462fd136fd1ca975a08 Mon Sep 17 00:00:00 2001 From: Philip Stoev Date: Mon, 11 Jan 2016 12:03:35 +0200 Subject: [PATCH 09/12] Bump WSREP_PATCH_VERSION in cmake/wsrep.cmake to 14 --- cmake/wsrep.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 8c5d9ee5212..7da525c9fea 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -18,7 +18,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "13") +SET(WSREP_PATCH_VERSION "14") # MariaDB addition: Revision number of the last revision merged from # codership branch visible in @@visible_comment. From b83de1151aab6dcc9f300159e31198364000de70 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 10 Feb 2016 18:04:08 -0500 Subject: [PATCH 10/12] Update WSREP_PATCH_REVNO. --- cmake/wsrep.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 7da525c9fea..6d92537e40f 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -23,7 +23,7 @@ SET(WSREP_PATCH_VERSION "14") # MariaDB addition: Revision number of the last revision merged from # codership branch visible in @@visible_comment. # Branch : https://github.com/codership/mysql-wsrep/tree/5.5 -SET(WSREP_PATCH_REVNO "4f81026") # Should be updated on every merge. +SET(WSREP_PATCH_REVNO "9949137") # Should be updated on every merge. # MariaDB: Obtain patch revision number: # Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set. From 02259623b9e4902a1188d303297e557d893dac40 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 16 Feb 2016 17:14:11 -0500 Subject: [PATCH 11/12] Update global_suppressions for galera suite to include new warning. --- mysql-test/suite/galera/suite.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 8fcc9cfa99e..fdaf64580c7 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -25,7 +25,8 @@ return "No my_print_defaults" unless $epath; push @::global_suppressions, ( qr(WSREP: wsrep_sst_receive_address is set to '127.0.0.1), - qr(WSREP: Could not open saved state file for reading: ), + qr(WSREP: Could not open saved state file for reading: .*), + qr(WSREP: Could not open state file for reading: .*), qr(WSREP: Gap in state sequence. Need state transfer.), qr(WSREP: Failed to prepare for incremental state transfer:), qr(WSREP:.*down context.*), From 3042d655e2c20dccf00fba6a64f72385330d2b7a Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 17 Feb 2016 15:50:01 -0500 Subject: [PATCH 12/12] MDEV-9577: sys_vars.ignore_db_dirs_basic fails under Valgrind Ensure that the command line argument is of sufficient length before moving past the leading long option marker "--". --- sql/wsrep_check_opts.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sql/wsrep_check_opts.cc b/sql/wsrep_check_opts.cc index 75894061d3f..188f0696bff 100644 --- a/sql/wsrep_check_opts.cc +++ b/sql/wsrep_check_opts.cc @@ -151,7 +151,20 @@ find_opts (argv_copy& a, struct opt* const opts) { for (int i = 0; i < a.argc_; ++i) { - char* ptr = a.argv_[i] + 2; // we're interested only in long options + char *ptr; + + /* + We're interested only in long options, ensure that the arg is of + sufficient length. + */ + if (strlen(a.argv_[i]) > 2) + { + ptr= a.argv_[i] + 2; + } + else + { + continue; + } struct opt* opt = opts; for (; 0 != opt->name; ++opt)