From 61c0df94655f2dc3146456e49f3f51610251e79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 23 Apr 2020 10:30:58 +0300 Subject: [PATCH 01/35] After-merge fix mysqld_exit(): Change the assertion failure on global_status_var.global_memory_used == 0 to fprintf, like in 0bcb65d358087bf94e217254f812f913343a6f5d It appears that in some cases, that variable may be nonzero even when LeakSanitizer (WITH_ASAN) would not report errors. This was observed in 10.4 88cf6f1c7ff5d56138c8b53a5adaca4c61752f86 with the MDEV-22348 test case (Aria startup failure when running main.default_storage_engine). --- sql/mysqld.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 74c153d57e9..2530043a729 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2191,10 +2191,10 @@ static void mysqld_exit(int exit_code) set_malloc_size_cb(NULL); if (global_status_var.global_memory_used) { -#ifdef SAFEMALLOC - sf_report_leaked_memory(0); -#endif - DBUG_SLOW_ASSERT(global_status_var.global_memory_used == 0); + fprintf(stderr, "Warning: Memory not freed: %lld\n", + (longlong) global_status_var.global_memory_used); + if (exit_code == 0) + SAFEMALLOC_REPORT_MEMORY(0); } cleanup_tls(); DBUG_LEAVE; From 5d856760fb3941b4a36cc484e28c500236c45ac1 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Thu, 23 Apr 2020 04:49:24 +0300 Subject: [PATCH 02/35] MDEV-22349 MTR re-bootstrap modifies environment variable MYSQLD_BOOTSTRAP_CMD --- mysql-test/mysql-test-run.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index fc152b232ca..80abc0fbb82 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3167,7 +3167,8 @@ sub mysql_install_db { # ---------------------------------------------------------------------- # export MYSQLD_BOOTSTRAP_CMD variable containing /mysqld # ---------------------------------------------------------------------- - $ENV{'MYSQLD_BOOTSTRAP_CMD'}= "$exe_mysqld_bootstrap " . join(" ", @$args); + $ENV{'MYSQLD_BOOTSTRAP_CMD'}= "$exe_mysqld_bootstrap " . join(" ", @$args) + unless defined $ENV{'MYSQLD_BOOTSTRAP_CMD'}; # Extra options can come not only from the command line, but also # from option files or combinations. We want them on a command line From 9f19dbe0c3f6bc3ee68c336869c186dd820107c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 23 Apr 2020 19:33:55 +0300 Subject: [PATCH 03/35] MDEV-22358 Assertion srv_undo_sources || ... in row_prebuilt_free() row_prebuilt_free(): Do not attempt to drop orphan indexes that might have been left behind by a failed ADD UNIQUE INDEX. This avoids the execution of unwanted transactions during shutdown. --- mysql-test/suite/innodb_fts/r/innodb_fts_misc.result | 7 ++++++- mysql-test/suite/innodb_fts/t/innodb_fts_misc.test | 8 +++++++- storage/innobase/row/row0mysql.cc | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result b/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result index 8c3c3b5be68..8074260952a 100644 --- a/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result +++ b/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result @@ -740,6 +740,11 @@ FULLTEXT(f2), FOREIGN KEY(f1) REFERENCES mdev20987_1(f1))ENGINE=InnoDB; INSERT INTO mdev20987_1 VALUES(1); INSERT INTO mdev20987_2 VALUES(1, 'mariadb'); +CREATE TABLE mdev22358 (a INT, b TEXT, FULLTEXT KEY ftidx (b)) ENGINE=InnoDB; +ALTER TABLE mdev22358 DROP KEY ftidx; +INSERT INTO mdev22358 (a) VALUES (2),(2); +ALTER TABLE mdev22358 ADD UNIQUE KEY uidx (a), ADD FULLTEXT KEY ftidx (b); +ERROR 23000: Duplicate entry '2' for key 'uidx' SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( @@ -747,7 +752,7 @@ t2 CREATE TABLE `t2` ( PRIMARY KEY (`FTS_DOC_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DELETE FROM t1 WHERE MATCH(char_column) AGAINST ('bbb'); -DROP TABLE t1, t2, mdev20987_2, mdev20987_1; +DROP TABLE t1, t2, mdev20987_2, mdev20987_1, mdev22358; "----------Test28---------" create table `fts_test`(`a` text,fulltext key(`a`))engine=innodb; set session autocommit=0; diff --git a/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test b/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test index 5b11a418dab..d1c6063d524 100644 --- a/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test +++ b/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test @@ -672,10 +672,16 @@ CREATE TABLE mdev20987_2(f1 INT NOT NULL, f2 CHAR(100), FOREIGN KEY(f1) REFERENCES mdev20987_1(f1))ENGINE=InnoDB; INSERT INTO mdev20987_1 VALUES(1); INSERT INTO mdev20987_2 VALUES(1, 'mariadb'); + +CREATE TABLE mdev22358 (a INT, b TEXT, FULLTEXT KEY ftidx (b)) ENGINE=InnoDB; +ALTER TABLE mdev22358 DROP KEY ftidx; +INSERT INTO mdev22358 (a) VALUES (2),(2); +--error ER_DUP_ENTRY +ALTER TABLE mdev22358 ADD UNIQUE KEY uidx (a), ADD FULLTEXT KEY ftidx (b); --source include/restart_mysqld.inc SHOW CREATE TABLE t2; DELETE FROM t1 WHERE MATCH(char_column) AGAINST ('bbb'); -DROP TABLE t1, t2, mdev20987_2, mdev20987_1; +DROP TABLE t1, t2, mdev20987_2, mdev20987_1, mdev22358; --echo "----------Test28---------" create table `fts_test`(`a` text,fulltext key(`a`))engine=innodb; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index c708842b04d..ac44e32c326 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1033,7 +1033,7 @@ row_prebuilt_free( rtr_clean_rtr_info(prebuilt->rtr_info, true); } if (prebuilt->table) { - dict_table_close(prebuilt->table, dict_locked, TRUE); + dict_table_close(prebuilt->table, dict_locked, FALSE); } mem_heap_free(prebuilt->heap); From 57ec41d6ea5d9384b45d026b70b3fd97ddd2861b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 24 Apr 2020 10:42:08 +0300 Subject: [PATCH 04/35] Cleanup: Remove a constant parameter row_vers_vc_matches_cluster(): Remove the parameter in_purge, which was always passed as in_purge=true. This parameter became constant in mysql/mysql-server@1dec14d346ac55fe72989dccb071f84b3b0d3bd6 and it always was constant in MariaDB starting from the introduction of the function in commit 2e814d4702d71a04388386a9f591d14a35980bfe (MariaDB 10.2.2). --- storage/innobase/row/row0vers.cc | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 3a4b560670f..b3d0e93b732 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -619,7 +619,6 @@ row_vers_build_cur_vrow_low( /** Check a virtual column value index secondary virtual index matches that of current cluster index record, which is recreated from information stored in undo log -@param[in] in_purge called by purge thread @param[in] rec record in the clustered index @param[in] icentry the index entry built from a cluster row @param[in] clust_index cluster index @@ -635,7 +634,6 @@ stored in undo log static bool row_vers_vc_matches_cluster( - bool in_purge, const rec_t* rec, const dtuple_t* icentry, dict_index_t* clust_index, @@ -696,12 +694,6 @@ row_vers_vc_matches_cluster( version = rec; - /* If this is called by purge thread, set TRX_UNDO_PREV_IN_PURGE - bit to search the undo log until we hit the current undo log with - roll_ptr */ - ulint status = (in_purge ? TRX_UNDO_PREV_IN_PURGE : 0) - | TRX_UNDO_GET_OLD_V_VALUE; - while (n_cmp_v_col < n_fields - n_non_v_col) { heap2 = heap; heap = mem_heap_create(1024); @@ -709,11 +701,12 @@ row_vers_vc_matches_cluster( version, clust_index, clust_offsets); ut_ad(cur_roll_ptr != 0); - ut_ad(in_purge == (roll_ptr != 0)); + ut_ad(roll_ptr != 0); trx_undo_prev_version_build( rec, mtr, version, clust_index, clust_offsets, - heap, &prev_version, NULL, vrow, status); + heap, &prev_version, NULL, vrow, + TRX_UNDO_PREV_IN_PURGE | TRX_UNDO_GET_OLD_V_VALUE); if (heap2) { mem_heap_free(heap2); @@ -997,7 +990,7 @@ row_vers_old_has_index_entry( secondary indexes.) */ if (entry && row_vers_vc_matches_cluster( - also_curr, rec, entry, + rec, entry, clust_index, clust_offsets, index, ientry, roll_ptr, trx_id, NULL, &vrow, mtr)) { From da7564edcf239fe7bc612efed97cc7b6fa89320b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 24 Apr 2020 10:46:33 +0300 Subject: [PATCH 05/35] Cleanup: Make row_upd_store_row() static --- storage/innobase/include/row0upd.h | 12 +----------- storage/innobase/row/row0upd.cc | 1 + 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index e08c9dd6b48..cca86590f74 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, MariaDB Corporation. +Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -371,16 +371,6 @@ row_upd_changes_some_index_ord_field_binary( /*========================================*/ const dict_table_t* table, /*!< in: table */ const upd_t* update);/*!< in: update vector for the row */ -/** Stores to the heap the row on which the node->pcur is positioned. -@param[in] node row update node -@param[in] thd mysql thread handle -@param[in,out] mysql_table NULL, or mysql table object when - user thread invokes dml */ -void -row_upd_store_row( - upd_node_t* node, - THD* thd, - TABLE* mysql_table); /***********************************************************//** Updates a row in a table. This is a high-level function used in SQL execution graphs. diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index fd7d622aa69..943e31d99fe 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2206,6 +2206,7 @@ row_upd_store_v_row( @param[in] thd mysql thread handle @param[in,out] mysql_table NULL, or mysql table object when user thread invokes dml */ +static void row_upd_store_row( upd_node_t* node, From 2c5067b6890974d0df335a833ed7a4e4c6ced183 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Tue, 7 Apr 2020 13:14:41 +0300 Subject: [PATCH 06/35] cleanup THR_KEY_mysys read TLS with my_thread_var write TLS with set_mysys_var() my_thread_var is no longer __attribute__ ((const)): this attribute is simply incorrect here. Read gcc manual for more information. sql/threadpool_generic.cc fails with that attribute. --- include/my_pthread.h | 3 ++- mysys/my_thr_init.c | 14 +++++++------- sql/threadpool_common.cc | 11 +++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/my_pthread.h b/include/my_pthread.h index 72647b6c9f7..f369b765edd 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -729,13 +729,14 @@ struct st_my_thread_var #endif }; -extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const)); +struct st_my_thread_var *_my_thread_var(void); extern void **my_thread_var_dbug(void); extern safe_mutex_t **my_thread_var_mutex_in_use(void); extern uint my_thread_end_wait_time; extern my_bool safe_mutex_deadlock_detector; #define my_thread_var (_my_thread_var()) #define my_errno my_thread_var->thr_errno +int set_mysys_var(struct st_my_thread_var *mysys_var); /* Keep track of shutdown,signal, and main threads so that my_end() will not report errors with them diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 8e38bd7c826..5686dabf35d 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -141,7 +141,7 @@ void my_thread_global_reinit(void) my_thread_destroy_internal_mutex(); my_thread_init_internal_mutex(); - tmp= my_pthread_getspecific(struct st_my_thread_var*, THR_KEY_mysys); + tmp= my_thread_var; DBUG_ASSERT(tmp); my_thread_destory_thr_mutex(tmp); @@ -279,7 +279,7 @@ my_bool my_thread_init(void) fprintf(stderr,"my_thread_init(): pthread_self: %p\n", pthread_self()); #endif - if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys)) + if (my_thread_var) { #ifdef EXTRA_DEBUG_THREADS fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n", @@ -297,7 +297,7 @@ my_bool my_thread_init(void) error= 1; goto end; } - pthread_setspecific(THR_KEY_mysys,tmp); + set_mysys_var(tmp); tmp->pthread_self= pthread_self(); my_thread_init_thr_mutex(tmp); @@ -334,7 +334,7 @@ end: void my_thread_end(void) { struct st_my_thread_var *tmp; - tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + tmp= my_thread_var; #ifdef EXTRA_DEBUG_THREADS fprintf(stderr,"my_thread_end(): tmp: %p pthread_self: %p thread_id: %ld\n", @@ -357,7 +357,7 @@ void my_thread_end(void) as the key is used by DBUG. */ DBUG_POP(); - pthread_setspecific(THR_KEY_mysys,0); + set_mysys_var(NULL); if (tmp && tmp->init) { @@ -441,7 +441,7 @@ extern void **my_thread_var_dbug() struct st_my_thread_var *tmp; if (!my_thread_global_init_done) return NULL; - tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + tmp= my_thread_var; return tmp && tmp->init ? &tmp->dbug : 0; } #endif /* DBUG_OFF */ @@ -453,7 +453,7 @@ safe_mutex_t **my_thread_var_mutex_in_use() struct st_my_thread_var *tmp; if (!my_thread_global_init_done) return NULL; - tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + tmp= my_thread_var; return tmp ? &tmp->mutex_in_use : 0; } diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index 0a374147e07..b0438770aae 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -45,7 +45,6 @@ static void threadpool_remove_connection(THD *thd); static int threadpool_process_request(THD *thd); static THD* threadpool_add_connection(CONNECT *connect, void *scheduler_data); -extern "C" pthread_key(struct st_my_thread_var*, THR_KEY_mysys); extern bool do_command(THD*); static inline TP_connection *get_TP_connection(THD *thd) @@ -87,7 +86,7 @@ struct Worker_thread_context #ifdef HAVE_PSI_THREAD_INTERFACE psi_thread = PSI_THREAD_CALL(get_thread)(); #endif - mysys_var= (st_my_thread_var *)pthread_getspecific(THR_KEY_mysys); + mysys_var= my_thread_var; } void restore() @@ -95,7 +94,7 @@ struct Worker_thread_context #ifdef HAVE_PSI_THREAD_INTERFACE PSI_THREAD_CALL(set_thread)(psi_thread); #endif - pthread_setspecific(THR_KEY_mysys,mysys_var); + set_mysys_var(mysys_var); pthread_setspecific(THR_THD, 0); } }; @@ -141,7 +140,7 @@ static inline void set_thd_idle(THD *thd) */ static void thread_attach(THD* thd) { - pthread_setspecific(THR_KEY_mysys,thd->mysys_var); + set_mysys_var(thd->mysys_var); thd->thread_stack=(char*)&thd; thd->store_globals(); #ifdef HAVE_PSI_THREAD_INTERFACE @@ -228,9 +227,9 @@ static THD* threadpool_add_connection(CONNECT *connect, void *scheduler_data) Store them in THD. */ - pthread_setspecific(THR_KEY_mysys, 0); + set_mysys_var(NULL); my_thread_init(); - st_my_thread_var* mysys_var= (st_my_thread_var *)pthread_getspecific(THR_KEY_mysys); + st_my_thread_var* mysys_var= my_thread_var; if (!mysys_var ||!(thd= connect->create_thd(NULL))) { /* Out of memory? */ From 81511b477676da29bcee7ca7f497b73af8a8f1d5 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 26 Apr 2020 15:13:26 +0300 Subject: [PATCH 07/35] Fixed shutdown crash in Aria that affects debug binaries MDEV-18286 Assertion `pagecache->cnt_for_resize_op == 0' failed in check_pagecache_is_cleaned_up on server shutdown The reason for the crash is that the counter-of-pinned-pages in the Aria pagecache goes wrong. This only affects debug builds, as in these we do an assert on shutdown if the counter-of-pinned-pages is not 0 (some page was left pinned). The bug was that in 2 places in the page cache, when not succeeding to pin a page and a retry was made, the counter-of-pinned-pages counter was not properly adjusted. In the given test case, BLOCK_COMMIT flushed all Aria files. If a block was flushed at the same time the insert tried to access it, the insert would retry to get the block and that would cause the counter to go wrong. --- storage/maria/ma_pagecache.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index f486d8c704f..e411cfbd54c 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -152,7 +152,7 @@ struct st_pagecache_hash_link /* simple states of a block */ #define PCBLOCK_ERROR 1 /* an error occurred when performing disk i/o */ -#define PCBLOCK_READ 2 /* the is page in the block buffer */ +#define PCBLOCK_READ 2 /* there is an active page in the block buffer */ /* A tread is reading the data to the page. @@ -3431,6 +3431,7 @@ restart: */ if (reg_request) unreg_request(pagecache, block, 1); + dec_counter_for_resize_op(pagecache); pagecache_pthread_mutex_unlock(&pagecache->cache_lock); DBUG_PRINT("info", ("restarting...")); goto restart; @@ -3707,6 +3708,7 @@ my_bool pagecache_delete_by_link(PAGECACHE *pagecache, DBUG_ASSERT((block->status & (PCBLOCK_IN_SWITCH | PCBLOCK_REASSIGNED)) == 0); + /* This lock is deleted in pagecache_delete_internal() called below */ inc_counter_for_resize_op(pagecache); /* make_lock_and_pin() can't fail here, because we are keeping pin on the @@ -3851,6 +3853,7 @@ restart: */ if (pin == PAGECACHE_PIN) unreg_request(pagecache, block, 1); + dec_counter_for_resize_op(pagecache); pagecache_pthread_mutex_unlock(&pagecache->cache_lock); DBUG_PRINT("info", ("restarting...")); goto restart; From d28ee189b794d3ceebd4a108da5653a1e38279e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 27 Apr 2020 09:36:31 +0300 Subject: [PATCH 08/35] MDEV-22271: Follow-up fix of --embedded Since commit 7198c6ab2dc8f8286f6732824ab985a76ebaaddc the ./mtr --embedded tests would fail to start innodb_plugin because of an undefined reference to the symbol wsrep_log(). Let us define a stub for that function. The embedded server is never built WITH_WSREP, but there are no separate storage engine builds for the embedded server. Hence, by default, the dynamic InnoDB storage engine plugin would be built WITH_WSREP and it would fail to load into the embedded server library due to a reference to the undefined symbol. --- sql/mysqld.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4580da89f16..e2cc7390385 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2018, MariaDB + Copyright (c) 2008, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1814,6 +1814,15 @@ static void close_server_sock() #endif } +#else /* EMBEDDED LIBRARY */ +# ifndef _WIN32 +/* Unfortunately, ha_innodb.so is by default built WITH_WSREP, and it +will be used for both the normal and the embedded server, while the +embedded server library is never built WITH_WSREP. We must define this +symbol in the embedded library, so that loading a dynamic InnoDB storage +engine plugin will work in the embedded server library. */ +void wsrep_log(void (*)(const char *, ...), const char *, ...) {} +# endif #endif /*EMBEDDED_LIBRARY*/ From 6a3fc1101cd8cfc8ae755f81a22d16cd98c03210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 27 Apr 2020 09:40:10 +0300 Subject: [PATCH 09/35] Aria: Avoid unused variables in embedded server --- storage/maria/ha_maria.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 5f73a1dc1af..6355781e19c 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -296,7 +296,7 @@ static MYSQL_SYSVAR_BOOL(encrypt_tables, maria_encrypt_tables, PLUGIN_VAR_OPCMDA "and not FIXED/DYNAMIC)", 0, 0, 0); -#ifdef HAVE_PSI_INTERFACE +#if defined HAVE_PSI_INTERFACE && !defined EMBEDDED_LIBRARY static PSI_mutex_info all_aria_mutexes[]= { From 758fbec6e3dd5f640c6e2eb1a78675e369540adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 13 Mar 2020 08:37:22 +0200 Subject: [PATCH 10/35] Fix clang 10 warnings _ma_fetch_keypage(): Correct an assertion that used to always hold. Thanks to clang -Wint-in-bool-context for flagging this. double_to_datetime_with_warn(): Suppress -Wimplicit-int-float-conversion by adding a cast. LONGLONG_MAX converted to double will actually be LONGLONG_MAX+1. --- sql/sql_time.cc | 4 ++-- storage/maria/ma_page.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sql/sql_time.cc b/sql/sql_time.cc index 6d94de047e8..421eb79c7a3 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. - Copyright (c) 2009, 2013 Monty Program Ab. + Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -402,7 +402,7 @@ bool double_to_datetime_with_warn(double value, MYSQL_TIME *ltime, if (neg) value= -value; - if (value > LONGLONG_MAX) + if (value > static_cast(LONGLONG_MAX)) value= static_cast(LONGLONG_MAX); longlong nr= static_cast(floor(value)); diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c index 7067421b51a..e1d41d1a1d8 100644 --- a/storage/maria/ma_page.c +++ b/storage/maria/ma_page.c @@ -1,4 +1,5 @@ /* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -112,7 +113,7 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info, if (lock != PAGECACHE_LOCK_LEFT_UNLOCKED) { - DBUG_ASSERT(lock == PAGECACHE_LOCK_WRITE || PAGECACHE_LOCK_READ); + DBUG_ASSERT(lock == PAGECACHE_LOCK_WRITE || lock == PAGECACHE_LOCK_READ); page_link.unlock= (lock == PAGECACHE_LOCK_WRITE ? PAGECACHE_LOCK_WRITE_UNLOCK : PAGECACHE_LOCK_READ_UNLOCK); From 6be05ceb05609b1aa7382776b4e27ad134808eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 27 Apr 2020 09:40:51 +0300 Subject: [PATCH 11/35] MDEV-22203: WSREP_ON is unnecessarily expensive to evaluate This is a backport of the applicable part of commit 93475aff8de80a0ef53cbee924bcb70de6e86f2c and commit 2c39f69d34e64a5cf94720e82e78c0ee91bd4649 from 10.4. Before 10.4 and Galera 4, WSREP_ON is a macro that points to a global Boolean variable, so it is not that expensive to evaluate, but we will add an unlikely() hint around it. WSREP_ON_NEW: Remove. This macro was introduced in commit c863159c320008676aff978a7cdde5732678f975 when reverting WSREP_ON to its previous definition. We replace some use of WSREP_ON with WSREP(thd), like it was done in 93475aff8de80a0ef53cbee924bcb70de6e86f2c. Note: the macro WSREP() in 10.1 is equivalent to WSREP_NNULL() in 10.4. Item_func_rand::seed_random(): Avoid invoking current_thd when WSREP is not enabled. --- mysql-test/suite/galera/t/MW-86-wait1.test | 1 + sql/item_func.cc | 23 +++++++++++----------- sql/log.cc | 9 +++++---- sql/log_event.cc | 8 ++++---- sql/mysqld.cc | 2 ++ sql/slave.cc | 8 +++++--- sql/sql_base.cc | 4 ++-- sql/sql_parse.cc | 8 ++++---- sql/sql_table.cc | 4 ++-- sql/wsrep_mysqld.h | 8 +------- 10 files changed, 38 insertions(+), 37 deletions(-) diff --git a/mysql-test/suite/galera/t/MW-86-wait1.test b/mysql-test/suite/galera/t/MW-86-wait1.test index 40a7882829b..a7476b74e68 100644 --- a/mysql-test/suite/galera/t/MW-86-wait1.test +++ b/mysql-test/suite/galera/t/MW-86-wait1.test @@ -5,6 +5,7 @@ # --source include/galera_cluster.inc --source include/have_binlog_format_row.inc +--source include/have_debug.inc --source include/have_debug_sync.inc --connection node_2 diff --git a/sql/item_func.cc b/sql/item_func.cc index 302ec58a708..8407dc881be 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB + Copyright (c) 2009, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2650,19 +2650,20 @@ void Item_func_rand::seed_random(Item *arg) TODO: do not do reinit 'rand' for every execute of PS/SP if args[0] is a constant. */ - uint32 tmp; + uint32 tmp= (uint32) arg->val_int(); #ifdef WITH_WSREP - THD *thd= current_thd; - if (WSREP(thd)) + if (WSREP_ON) { - if (thd->wsrep_exec_mode==REPL_RECV) - tmp= thd->wsrep_rand; - else - tmp= thd->wsrep_rand= (uint32) arg->val_int(); - } - else + THD *thd= current_thd; + if (thd->variables.wsrep_on) + { + if (thd->wsrep_exec_mode==REPL_RECV) + tmp= thd->wsrep_rand; + else + thd->wsrep_rand= tmp; + } + } #endif /* WITH_WSREP */ - tmp= (uint32) arg->val_int(); my_rnd_init(rand, (uint32) (tmp*0x10001L+55555555L), (uint32) (tmp*0x10000001L)); diff --git a/sql/log.cc b/sql/log.cc index 0efef6d1e29..076dd36a219 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1791,7 +1791,7 @@ binlog_commit_flush_stmt_cache(THD *thd, bool all, #ifdef WITH_WSREP if (thd->wsrep_mysql_replicated > 0) { - DBUG_ASSERT(WSREP_ON); + DBUG_ASSERT(WSREP(thd)); WSREP_DEBUG("avoiding binlog_commit_flush_trx_cache: %d", thd->wsrep_mysql_replicated); return 0; @@ -6612,14 +6612,15 @@ int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge) int error= 0; DBUG_ENTER("MYSQL_BIN_LOG::rotate"); - if (wsrep_to_isolation) +#ifdef WITH_WSREP + if (WSREP_ON && wsrep_to_isolation) { - DBUG_ASSERT(WSREP_ON); *check_purge= false; - WSREP_DEBUG("avoiding binlog rotate due to TO isolation: %d", + WSREP_DEBUG("avoiding binlog rotate due to TO isolation: %d", wsrep_to_isolation); DBUG_RETURN(0); } +#endif /* WITH_WSREP */ //todo: fix the macro def and restore safe_mutex_assert_owner(&LOCK_log); *check_purge= false; diff --git a/sql/log_event.cc b/sql/log_event.cc index d731c39d9c5..bb3465ae9f0 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. - Copyright (c) 2009, 2019, MariaDB + Copyright (c) 2009, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -4770,7 +4770,7 @@ Query_log_event::do_shall_skip(rpl_group_info *rgi) } } #ifdef WITH_WSREP - else if (WSREP_ON && wsrep_mysql_replication_bundle && opt_slave_domain_parallel_threads == 0 && + else if (WSREP(thd) && wsrep_mysql_replication_bundle && opt_slave_domain_parallel_threads == 0 && thd->wsrep_mysql_replicated > 0 && (is_begin() || is_commit())) { @@ -4784,7 +4784,7 @@ Query_log_event::do_shall_skip(rpl_group_info *rgi) thd->wsrep_mysql_replicated = 0; } } -#endif +#endif /* WITH_WSREP */ DBUG_RETURN(Log_event::do_shall_skip(rgi)); } @@ -7755,7 +7755,7 @@ Xid_log_event::do_shall_skip(rpl_group_info *rgi) DBUG_RETURN(Log_event::EVENT_SKIP_COUNT); } #ifdef WITH_WSREP - else if (wsrep_mysql_replication_bundle && WSREP_ON && + else if (WSREP(thd) && wsrep_mysql_replication_bundle && opt_slave_domain_parallel_threads == 0) { if (++thd->wsrep_mysql_replicated < (int)wsrep_mysql_replication_bundle) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e2cc7390385..ff3faaa92bc 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5781,8 +5781,10 @@ int mysqld_main(int argc, char **argv) set_user(mysqld_user, user_info); } +#ifdef WITH_WSREP if (WSREP_ON && wsrep_check_opts()) global_system_variables.wsrep_on= 0; +#endif if (opt_bin_log && !global_system_variables.server_id) { diff --git a/sql/slave.cc b/sql/slave.cc index cbfc3fd8413..26fabc2cc52 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB Corporation + Copyright (c) 2009, 2020, MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -4998,8 +4998,10 @@ pthread_handler_t handle_slave_sql(void *arg) if (!sql_slave_killed(serial_rgi)) { slave_output_error_info(serial_rgi, thd); - if (WSREP_ON && rli->last_error().number == ER_UNKNOWN_COM_ERROR) + if (WSREP(thd) && rli->last_error().number == ER_UNKNOWN_COM_ERROR) + { wsrep_node_dropped= TRUE; + } } goto err; } @@ -5131,7 +5133,7 @@ err_during_init: If slave stopped due to node going non primary, we set global flag to trigger automatic restart of slave when node joins back to cluster. */ - if (WSREP_ON && wsrep_node_dropped && wsrep_restart_slave) + if (WSREP(thd) && wsrep_node_dropped && wsrep_restart_slave) { if (wsrep_ready_get()) { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 1c4e7600d87..1dbed8c55d1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2010, 2016, MariaDB + Copyright (c) 2010, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -4784,7 +4784,7 @@ restart: } } - if (WSREP_ON && + if (WSREP(thd) && wsrep_replicate_myisam && (*start) && (*start)->table && diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e5626ccbd7c..d19cbf5ad9b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2008, 2019, MariaDB + Copyright (c) 2008, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1493,7 +1493,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (parser_state.init(thd, thd->query(), thd->query_length())) break; - if (WSREP_ON) + if (WSREP(thd)) wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); else mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); @@ -1574,13 +1574,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, */ statistic_increment(thd->status_var.questions, &LOCK_status); - if(!WSREP(thd)) + if (!WSREP(thd)) thd->set_time(); /* Reset the query start time. */ parser_state.reset(beginning_of_next_stmt, length); /* TODO: set thd->lex->sql_command to SQLCOM_END here */ - if (WSREP_ON) + if (WSREP(thd)) wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); else mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e694c52e272..ef6a8c01843 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. - Copyright (c) 2010, 2019, MariaDB + Copyright (c) 2010, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -5338,7 +5338,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, DBUG_ENTER("mysql_create_like_table"); #ifdef WITH_WSREP - if (WSREP_ON && !thd->wsrep_applier && + if (WSREP(thd) && !thd->wsrep_applier && wsrep_create_like_table(thd, table, src_table, create_info)) DBUG_RETURN(res); #endif diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index a5ec69268d4..1531abe78f8 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -179,13 +179,7 @@ extern void wsrep_prepend_PATH (const char* path); /* Other global variables */ extern wsrep_seqno_t wsrep_locked_seqno; -#define WSREP_ON \ - (global_system_variables.wsrep_on) - -#define WSREP_ON_NEW \ - ((global_system_variables.wsrep_on) && \ - wsrep_provider && \ - strcmp(wsrep_provider, WSREP_NONE)) +#define WSREP_ON unlikely(global_system_variables.wsrep_on) #define WSREP(thd) \ (WSREP_ON && thd->variables.wsrep_on) From f462fbac61445558a7b8929cabace8a9c480d961 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 21 Apr 2020 22:57:54 +0200 Subject: [PATCH 12/35] MDEV-22078 MariaDB-compat missing from MariaDB 10.4 CentOS 8 Yum Repo Backport INSALL_SYMLINK cmake macro from 10.3. It'll make libmysqlclient_r.* symlinks to link to the actual shared library file, not to another symlink. As a bonus it'll fix cmake warning about deprecated LOCATION property --- cmake/install_macros.cmake | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake index 0c05b06208f..bb89a57ab11 100644 --- a/cmake/install_macros.cmake +++ b/cmake/install_macros.cmake @@ -162,17 +162,13 @@ ENDFUNCTION() # and extension will be the same as for target file. MACRO(INSTALL_SYMLINK linkname target destination component) IF(UNIX) - GET_TARGET_PROPERTY(location ${target} LOCATION) - GET_FILENAME_COMPONENT(path ${location} PATH) - GET_FILENAME_COMPONENT(name ${location} NAME) - SET(output ${path}/${linkname}) + SET(output ${CMAKE_CURRENT_BINARY_DIR}/${linkname}) ADD_CUSTOM_COMMAND( OUTPUT ${output} - COMMAND ${CMAKE_COMMAND} ARGS -E remove -f ${output} + COMMAND ${CMAKE_COMMAND} ARGS -E remove -f ${linkname} COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink - ${name} + $ ${linkname} - WORKING_DIRECTORY ${path} DEPENDS ${target} ) From dd4124c22430dd2f245afbf9a20cfea303de3320 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 22 Apr 2020 13:21:43 +0200 Subject: [PATCH 13/35] MDEV-22271 Excessive stack memory usage due to WSREP_LOG fix embedded innodb_plugin tests followup for 7198c6ab2dc --- sql/mysqld.cc | 9 --------- sql/wsrep_dummy.cc | 4 ++++ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ff3faaa92bc..594f50b72f2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1814,15 +1814,6 @@ static void close_server_sock() #endif } -#else /* EMBEDDED LIBRARY */ -# ifndef _WIN32 -/* Unfortunately, ha_innodb.so is by default built WITH_WSREP, and it -will be used for both the normal and the embedded server, while the -embedded server library is never built WITH_WSREP. We must define this -symbol in the embedded library, so that loading a dynamic InnoDB storage -engine plugin will work in the embedded server library. */ -void wsrep_log(void (*)(const char *, ...), const char *, ...) {} -# endif #endif /*EMBEDDED_LIBRARY*/ diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc index 43cea8bad42..364ef2d3e7a 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -141,3 +141,7 @@ void wsrep_unlock_rollback() void wsrep_set_data_home_dir(const char *) { } + +void wsrep_log(void (*)(const char *, ...), const char *, ...) +{ +} From c2db9397c792a774748f22ddb33b994aae547770 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 21 Apr 2020 18:07:11 +0200 Subject: [PATCH 14/35] MDEV-18565 Galera mtr-suite fails if galera library is not installed revert/simplify f5390eea9a9 remove galera-specific checks from mtr and the main suite --- mysql-test/include/galera_have_debug_sync.inc | 2 +- mysql-test/include/have_garbd.inc | 4 - mysql-test/include/have_mariabackup.inc | 4 - mysql-test/lib/My/SafeProcess.pm | 6 - mysql-test/lib/My/SafeProcess/CMakeLists.txt | 2 + .../lib/My/SafeProcess/wsrep_check_version.c | 139 +++---------- mysql-test/mysql-test-run.pl | 192 ++---------------- mysql-test/suite.pm | 15 -- .../suite/galera/include/have_mariabackup.inc | 7 + mysql-test/suite/galera/suite.pm | 19 +- .../suite/galera/t/galera_ist_mariabackup.cnf | 3 + ...lera_ist_mariabackup_innodb_flush_logs.cnf | 3 + .../galera_3nodes}/include/galera_resume.inc | 0 .../galera_3nodes/include/have_garbd.inc | 3 + mysql-test/suite/galera_3nodes/suite.pm | 13 +- .../t/galera_innobackupex_backup.test | 2 +- mysql-test/suite/galera_sr/suite.pm | 13 +- mysql-test/suite/mariabackup/suite.pm | 3 +- mysql-test/suite/wsrep/common.pm | 117 +++++++++++ mysql-test/suite/wsrep/suite.pm | 13 +- .../wsrep_info/mysql-test/wsrep_info/suite.pm | 12 +- 21 files changed, 210 insertions(+), 362 deletions(-) delete mode 100644 mysql-test/include/have_garbd.inc delete mode 100644 mysql-test/include/have_mariabackup.inc create mode 100644 mysql-test/suite/galera/include/have_mariabackup.inc rename mysql-test/{ => suite/galera_3nodes}/include/galera_resume.inc (100%) create mode 100644 mysql-test/suite/galera_3nodes/include/have_garbd.inc create mode 100644 mysql-test/suite/wsrep/common.pm diff --git a/mysql-test/include/galera_have_debug_sync.inc b/mysql-test/include/galera_have_debug_sync.inc index 7c0156052d8..21e7b3c88c3 100644 --- a/mysql-test/include/galera_have_debug_sync.inc +++ b/mysql-test/include/galera_have_debug_sync.inc @@ -3,7 +3,7 @@ --let $galera_have_debug_sync = `SELECT 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters'` --if (!$galera_have_debug_sync) { - --skip "Test requires Galera debug library with debug_sync functionality" + --skip Test requires Galera debug library with debug_sync functionality } --enable_query_log diff --git a/mysql-test/include/have_garbd.inc b/mysql-test/include/have_garbd.inc deleted file mode 100644 index 0dd693f2c63..00000000000 --- a/mysql-test/include/have_garbd.inc +++ /dev/null @@ -1,4 +0,0 @@ -# -# suite.pm will make sure that all tests including this file -# will be skipped as needed -# diff --git a/mysql-test/include/have_mariabackup.inc b/mysql-test/include/have_mariabackup.inc deleted file mode 100644 index 0dd693f2c63..00000000000 --- a/mysql-test/include/have_mariabackup.inc +++ /dev/null @@ -1,4 +0,0 @@ -# -# suite.pm will make sure that all tests including this file -# will be skipped as needed -# diff --git a/mysql-test/lib/My/SafeProcess.pm b/mysql-test/lib/My/SafeProcess.pm index 87054019759..19f2893ea51 100644 --- a/mysql-test/lib/My/SafeProcess.pm +++ b/mysql-test/lib/My/SafeProcess.pm @@ -100,8 +100,6 @@ else $bindir = getcwd(); } -our $wsrep_check_version; - # Find the safe process binary or script sub find_bin { if (IS_WIN32PERL or IS_CYGWIN) @@ -121,10 +119,6 @@ sub find_bin { "my_safe_process"); push(@safe_process_cmd, $exe); } - # Wsrep version check utility: - $wsrep_check_version= - my_find_bin($bindir, ["lib/My/SafeProcess", "My/SafeProcess"], - "wsrep_check_version", NOT_REQUIRED); } diff --git a/mysql-test/lib/My/SafeProcess/CMakeLists.txt b/mysql-test/lib/My/SafeProcess/CMakeLists.txt index 4c3b62fa67e..44c0e6eb8cb 100644 --- a/mysql-test/lib/My/SafeProcess/CMakeLists.txt +++ b/mysql-test/lib/My/SafeProcess/CMakeLists.txt @@ -14,6 +14,8 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + IF (WIN32) ADD_EXECUTABLE(my_safe_process safe_process_win.cc) ADD_EXECUTABLE(my_safe_kill safe_kill_win.cc) diff --git a/mysql-test/lib/My/SafeProcess/wsrep_check_version.c b/mysql-test/lib/My/SafeProcess/wsrep_check_version.c index 91098be882a..7398bc8ad92 100644 --- a/mysql-test/lib/My/SafeProcess/wsrep_check_version.c +++ b/mysql-test/lib/My/SafeProcess/wsrep_check_version.c @@ -13,122 +13,39 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include -#include +#include #include -#include - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef _WIN32 -#include -#define dlsym(lib, name) GetProcAddress((HMODULE)lib, name) -#define dlopen(libname, unused) LoadLibraryEx(libname, NULL, 0) -#define dlclose(lib) FreeLibrary((HMODULE)lib) -#elif defined(HAVE_DLFCN_H) -#include -#else -#define NO_DLL -#endif - -#ifndef NO_DLL - #include "../../../../wsrep-lib/wsrep-API/v26/wsrep_api.h" -/************************************************************************** - * Library loader - **************************************************************************/ - -static int wsrep_check_iface_version(const char *found, const char *iface_ver) -{ - if (strcmp(found, iface_ver)) { - return ERANGE; - } - return 0; -} - -typedef int (*wsrep_loader_fun)(wsrep_t*); - -static wsrep_loader_fun wsrep_dlf(void *dlh, const char *sym) -{ - union { - wsrep_loader_fun dlfun; - void *obj; - } alias; - alias.obj = dlsym(dlh, sym); - return alias.dlfun; -} - -static int wsrep_check_version_symbol(void *dlh) -{ - char** dlversion = NULL; - dlversion = (char**) dlsym(dlh, "wsrep_interface_version"); - if (dlversion == NULL) - return EINVAL; - return wsrep_check_iface_version(*dlversion, WSREP_INTERFACE_VERSION); -} - -static int wsrep_print_version(void *dlh) -{ - char** dlversion = NULL; - dlversion = (char**) dlsym(dlh, "wsrep_interface_version"); - if (dlversion == NULL) - return EINVAL; - printf("found: %s, need: %s\n", *dlversion, WSREP_INTERFACE_VERSION); - return 0; -} - int main(int argc, char **argv) { - int rc = EINVAL; - void *dlh; - wsrep_loader_fun dlfun; - const char *provider= getenv("WSREP_PROVIDER"); + int rc= 1; + void *dlh; + const char *provider= getenv("WSREP_PROVIDER"); + char** dlversion= NULL; - if (!provider) - { - fprintf(stderr, "WSREP_PROVIDER is not set\n"); - return 1; - } - if (!(dlh = dlopen(provider, RTLD_NOW | RTLD_LOCAL))) - { - fprintf(stderr, "Can't open WSREP_PROVIDER (%s) library, error: %s\n", - provider, dlerror()); - goto err; - } - - if (!(dlfun = wsrep_dlf(dlh, "wsrep_loader"))) - { - fprintf(stderr, "Can't find 'wsrep_loader' symbol in %s\n", - provider); - goto err; - } - - if (argc < 2 || strcmp(argv[1], "-p")) { - rc = wsrep_check_version_symbol(dlh); - } - else { - rc = wsrep_print_version(dlh); - } - -err: - if (dlh) dlclose(dlh); - - if (rc == 0) - return 0; - else if (rc == ERANGE) - return 2; - else - return 1; -} - -#else - -int main(void) -{ + if (!provider || !*provider) + { + printf("WSREP_PROVIDER is not set\n"); return 1; -} + } + if (!(dlh= dlopen(provider, RTLD_NOW | RTLD_LOCAL))) + { + printf("Can't open WSREP_PROVIDER (%s) library, error: %s\n", + provider, dlerror()); + return 1; + } -#endif + dlversion= (char**) dlsym(dlh, "wsrep_interface_version"); + if (dlversion && *dlversion) + { + rc= strcmp(*dlversion, WSREP_INTERFACE_VERSION) ? 2 : 0; + if (rc) + printf("Wrong wsrep provider library version, found: %s, need: %s\n", *dlversion, WSREP_INTERFACE_VERSION); + } + else + printf("Galera library does not contain a version symbol"); + + dlclose(dlh); + return rc; +} diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index d2f31cd5de3..f26a09bff18 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -140,10 +140,6 @@ my $opt_start_dirty; my $opt_start_exit; my $start_only; my $file_wsrep_provider; -my $extra_path; -my $mariabackup_path; -my $mariabackup_exe; -my $garbd_exe; our @global_suppressions; @@ -379,170 +375,6 @@ $| = 1; # Automatically flush STDOUT main(); -sub have_wsrep() { - my $wsrep_on= $mysqld_variables{'wsrep-on'}; - return defined $wsrep_on -} - -sub have_wsrep_provider() { - return $file_wsrep_provider ne ""; -} - -sub have_mariabackup() { - return $mariabackup_path ne ""; -} - -sub have_garbd() { - return $garbd_exe ne ""; -} - -sub check_wsrep_version() { - if ($My::SafeProcess::wsrep_check_version ne "") { - system($My::SafeProcess::wsrep_check_version); - return ($? >> 8) == 0; - } - else { - return 0; - } -} - -sub wsrep_version_message() { - if ($My::SafeProcess::wsrep_check_version ne "") { - my $output= `$My::SafeProcess::wsrep_check_version -p`; - if (($? >> 8) == 0) { - $output =~ s/\s+\z//; - return "Wsrep provider version mismatch (".$output.")"; - } - else { - return "Galera library does not contain a version symbol"; - } - } - else { - return "Unable to find a wsrep version check utility"; - } -} - -sub which($) { return `sh -c "command -v $_[0]"` } - -sub check_garbd_support() { - if (defined $ENV{'MTR_GARBD_EXE'}) { - if (mtr_file_exists($ENV{'MTR_GARBD_EXE'}) ne "") { - $garbd_exe= $ENV{'MTR_GARBD_EXE'}; - } else { - mtr_error("MTR_GARBD_EXE env set to an invalid path"); - } - } - else { - my $wsrep_path= dirname($file_wsrep_provider); - $garbd_exe= - mtr_file_exists($wsrep_path."/garb/garbd", - $wsrep_path."/../../bin/garb/garbd"); - if ($garbd_exe ne "") { - $ENV{MTR_GARBD_EXE}= $garbd_exe; - } - } -} - -sub check_wsrep_support() { - $garbd_exe= ""; - if (have_wsrep()) { - mtr_report(" - binaries built with wsrep patch"); - - # ADD scripts to $PATH to that wsrep_sst_* can be found - my ($spath) = grep { -f "$_/wsrep_sst_rsync"; } "$bindir/scripts", $path_client_bindir; - mtr_error("No SST scripts") unless $spath; - my $separator= (IS_WINDOWS) ? ';' : ':'; - $ENV{PATH}="$spath$separator$ENV{PATH}"; - - # ADD mysql client library path to path so that wsrep_notify_cmd can find mysql - # client for loading the tables. (Don't assume each machine has mysql install) - my ($cpath) = grep { -f "$_/mysql"; } "$bindir/scripts", $path_client_bindir; - mtr_error("No scritps") unless $cpath; - $ENV{PATH}="$cpath$separator$ENV{PATH}" unless $cpath eq $spath; - - # ADD my_print_defaults script path to path so that SST scripts can find it - my $my_print_defaults_exe= - mtr_exe_maybe_exists( - "$bindir/extra/my_print_defaults", - "$path_client_bindir/my_print_defaults"); - my $epath= ""; - if ($my_print_defaults_exe ne "") { - $epath= dirname($my_print_defaults_exe); - } - mtr_error("No my_print_defaults") unless $epath; - $ENV{PATH}="$epath$separator$ENV{PATH}" unless ($epath eq $spath) or - ($epath eq $cpath); - - $extra_path= $epath; - - if (!IS_WINDOWS) { - if (which("socat")) { - $ENV{MTR_GALERA_TFMT}="socat"; - } elsif (which("nc")) { - $ENV{MTR_GALERA_TFMT}="nc"; - } - } - - # Check whether WSREP_PROVIDER environment variable is set. - if (defined $ENV{'WSREP_PROVIDER'}) { - $file_wsrep_provider= ""; - if ($ENV{'WSREP_PROVIDER'} ne "none") { - if (mtr_file_exists($ENV{'WSREP_PROVIDER'}) ne "") { - $file_wsrep_provider= $ENV{'WSREP_PROVIDER'}; - } else { - mtr_error("WSREP_PROVIDER env set to an invalid path"); - } - check_garbd_support(); - } - # WSREP_PROVIDER is valid; set to a valid path or "none"). - mtr_verbose("WSREP_PROVIDER env set to $ENV{'WSREP_PROVIDER'}"); - } else { - # WSREP_PROVIDER env not defined. Lets try to locate the wsrep provider - # library. - $file_wsrep_provider= - mtr_file_exists("/usr/lib64/galera-4/libgalera_smm.so", - "/usr/lib64/galera/libgalera_smm.so", - "/usr/lib/galera-4/libgalera_smm.so", - "/usr/lib/galera/libgalera_smm.so"); - if ($file_wsrep_provider ne "") { - # wsrep provider library found ! - mtr_verbose("wsrep provider library found : $file_wsrep_provider"); - $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; - check_garbd_support(); - } else { - mtr_verbose("Could not find wsrep provider library, setting it to 'none'"); - $ENV{'WSREP_PROVIDER'}= "none"; - } - } - } else { - $file_wsrep_provider= ""; - $extra_path= ""; - } -} - -sub check_mariabackup_support() { - $mariabackup_path= ""; - $mariabackup_exe= - mtr_exe_maybe_exists( - "$bindir/extra/mariabackup$opt_vs_config/mariabackup", - "$path_client_bindir/mariabackup"); - if ($mariabackup_exe ne "") { - my $bpath= dirname($mariabackup_exe); - my $separator= (IS_WINDOWS) ? ';' : ':'; - $ENV{PATH}="$bpath$separator$ENV{PATH}" unless $bpath eq $extra_path; - - $mariabackup_path= $bpath; - - $ENV{XTRABACKUP}= $mariabackup_exe; - - $ENV{XBSTREAM}= mtr_exe_maybe_exists( - "$bindir/extra/mariabackup/$opt_vs_config/mbstream", - "$path_client_bindir/mbstream"); - - $ENV{INNOBACKUPEX}= "$mariabackup_exe --innobackupex"; - } -} - sub main { $ENV{MTR_PERL}=$^X; @@ -587,8 +419,7 @@ sub main { } check_ssl_support(); check_debug_support(); - check_wsrep_support(); - check_mariabackup_support(); + environment_setup(); if (!$opt_suites) { $opt_suites= join ',', collect_default_suites(@DEFAULT_SUITES); @@ -2578,10 +2409,23 @@ sub environment_setup { my $exe_innochecksum= mtr_exe_maybe_exists("$bindir/extra$opt_vs_config/innochecksum", "$path_client_bindir/innochecksum"); - if ($exe_innochecksum) - { - $ENV{'INNOCHECKSUM'}= native_path($exe_innochecksum); - } + $ENV{'INNOCHECKSUM'}= native_path($exe_innochecksum) if $exe_innochecksum; + + # ---------------------------------------------------- + # mariabackup + # ---------------------------------------------------- + my $exe_mariabackup= mtr_exe_maybe_exists( + "$bindir/extra/mariabackup$opt_vs_config/mariabackup", + "$path_client_bindir/mariabackup"); + + $ENV{XTRABACKUP}= native_path($exe_mariabackup) if $exe_mariabackup; + + my $exe_xbstream= mtr_exe_maybe_exists( + "$bindir/extra/mariabackup/$opt_vs_config/mbstream", + "$path_client_bindir/mbstream"); + $ENV{XBSTREAM}= native_path($exe_xbstream) if $exe_xbstream; + + $ENV{INNOBACKUPEX}= "$exe_mariabackup --innobackupex"; # Create an environment variable to make it possible # to detect that valgrind is being used from test cases diff --git a/mysql-test/suite.pm b/mysql-test/suite.pm index 6666947b03d..cb30a3186e5 100644 --- a/mysql-test/suite.pm +++ b/mysql-test/suite.pm @@ -47,21 +47,6 @@ sub skip_combinations { $skip{'main/plugin_loaderr.test'} = 'needs compiled-in innodb' unless $::mysqld_variables{'innodb'} eq "ON"; - $skip{'include/have_mariabackup.inc'} = 'Need mariabackup' - unless ::have_mariabackup(); - - $skip{'include/have_mariabackup.inc'} = 'Need socket statistics utility' - unless IS_WINDOWS || ::which("ss"); - - $skip{'include/have_mariabackup.inc'} = 'Need socat or nc' - unless IS_WINDOWS || $ENV{MTR_GALERA_TFMT}; - - $skip{'include/have_garbd.inc'} = 'Need garbd' - unless ::have_garbd(); - - $skip{'include/have_file_key_management.inc'} = 'Needs file_key_management plugin' - unless $ENV{FILE_KEY_MANAGEMENT_SO}; - # disable tests that use ipv6, if unsupported sub ipv6_ok() { use Socket; diff --git a/mysql-test/suite/galera/include/have_mariabackup.inc b/mysql-test/suite/galera/include/have_mariabackup.inc new file mode 100644 index 00000000000..6c4ad240172 --- /dev/null +++ b/mysql-test/suite/galera/include/have_mariabackup.inc @@ -0,0 +1,7 @@ +if (!$XTRABACKUP) { + skip Needs mariabackup; +} + +if (!$MTR_GALERA_TFMT) { + skip Needs socat or nc; +} diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 4bce28aceb2..447c2b79d2b 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -1,16 +1,11 @@ package My::Suite::Galera; -use File::Basename; -use My::Find; + +use lib 'suite'; +use wsrep::common; @ISA = qw(My::Suite); -return "Not run for embedded server" if $::opt_embedded_server; - -return "WSREP is not compiled in" if not ::have_wsrep(); - -return "No wsrep provider library" unless ::have_wsrep_provider(); - -return ::wsrep_version_message() unless ::check_wsrep_version(); +return wsrep_not_ok() if wsrep_not_ok(); push @::global_suppressions, ( @@ -69,4 +64,10 @@ push @::global_suppressions, qr(WSREP: wsrep_sst_method is set to 'mysqldump' yet mysqld bind_address is set to .*), ); +sub skip_combinations { + my %skip = (); + $skip{'include/have_mariabackup.inc'} = 'Need ss' unless `ss -V`; + %skip; +} + bless { }; diff --git a/mysql-test/suite/galera/t/galera_ist_mariabackup.cnf b/mysql-test/suite/galera/t/galera_ist_mariabackup.cnf index 75dff78149d..2392071ccfe 100644 --- a/mysql-test/suite/galera/t/galera_ist_mariabackup.cnf +++ b/mysql-test/suite/galera/t/galera_ist_mariabackup.cnf @@ -10,3 +10,6 @@ wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' [mysqld.2] wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' +[sst] +transferfmt=@ENV.MTR_GALERA_TFMT +streamfmt=xbstream diff --git a/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf b/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf index 1542376b2b8..e98f37654cc 100644 --- a/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf +++ b/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf @@ -12,3 +12,6 @@ wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' [mysqld.2] wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' +[sst] +transferfmt=@ENV.MTR_GALERA_TFMT +streamfmt=xbstream diff --git a/mysql-test/include/galera_resume.inc b/mysql-test/suite/galera_3nodes/include/galera_resume.inc similarity index 100% rename from mysql-test/include/galera_resume.inc rename to mysql-test/suite/galera_3nodes/include/galera_resume.inc diff --git a/mysql-test/suite/galera_3nodes/include/have_garbd.inc b/mysql-test/suite/galera_3nodes/include/have_garbd.inc new file mode 100644 index 00000000000..560372c22e9 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/include/have_garbd.inc @@ -0,0 +1,3 @@ +if (!$MTR_GARBD_EXE) { + skip Needs garbd; +} diff --git a/mysql-test/suite/galera_3nodes/suite.pm b/mysql-test/suite/galera_3nodes/suite.pm index 4a861f3b9fa..b808db6a50a 100644 --- a/mysql-test/suite/galera_3nodes/suite.pm +++ b/mysql-test/suite/galera_3nodes/suite.pm @@ -1,16 +1,11 @@ package My::Suite::GALERA_3NODES; -use File::Basename; -use My::Find; + +use lib 'suite'; +use wsrep::common; @ISA = qw(My::Suite); -return "Not run for embedded server" if $::opt_embedded_server; - -return "WSREP is not compiled in" if not ::have_wsrep(); - -return "No wsrep provider library" unless ::have_wsrep_provider(); - -return ::wsrep_version_message() unless ::check_wsrep_version(); +return wsrep_not_ok() if wsrep_not_ok(); push @::global_suppressions, ( diff --git a/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test b/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test index 8dfb4660f3e..cd5c020ae38 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test +++ b/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test @@ -4,7 +4,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc ---source include/have_mariabackup.inc +--source suite/galera/include/have_mariabackup.inc --let $galera_connection_name = node_3 --let $galera_server_number = 3 diff --git a/mysql-test/suite/galera_sr/suite.pm b/mysql-test/suite/galera_sr/suite.pm index 878e2d0fffd..cc13421d66d 100644 --- a/mysql-test/suite/galera_sr/suite.pm +++ b/mysql-test/suite/galera_sr/suite.pm @@ -1,16 +1,11 @@ package My::Suite::Galera_sr; -use File::Basename; -use My::Find; + +use lib 'suite'; +use wsrep::common; @ISA = qw(My::Suite); -return "Not run for embedded server" if $::opt_embedded_server; - -return "WSREP is not compiled in" if not ::have_wsrep(); - -return "No wsrep provider library" unless ::have_wsrep_provider(); - -return ::wsrep_version_message() unless ::check_wsrep_version(); +return wsrep_not_ok() if wsrep_not_ok(); push @::global_suppressions, ( diff --git a/mysql-test/suite/mariabackup/suite.pm b/mysql-test/suite/mariabackup/suite.pm index 14e38d16158..f0db4482156 100644 --- a/mysql-test/suite/mariabackup/suite.pm +++ b/mysql-test/suite/mariabackup/suite.pm @@ -7,12 +7,13 @@ use strict; return "Not run for embedded server" if $::opt_embedded_server; -return "No mariabackup" unless ::have_mariabackup(); +return "No mariabackup" unless $ENV{XTRABACKUP}; my $have_qpress = index(`qpress 2>&1`,"Compression") > 0; sub skip_combinations { my %skip; + $skip{'include/have_file_key_management.inc'} = 'needs file_key_management plugin' unless $ENV{FILE_KEY_MANAGEMENT_SO}; $skip{'compress_qpress.test'}= 'needs qpress executable in PATH' unless $have_qpress; %skip; } diff --git a/mysql-test/suite/wsrep/common.pm b/mysql-test/suite/wsrep/common.pm new file mode 100644 index 00000000000..8ac3b3ea94c --- /dev/null +++ b/mysql-test/suite/wsrep/common.pm @@ -0,0 +1,117 @@ +package wsrep::common; + +use base qw(Exporter); +our @EXPORT= qw(wsrep_not_ok); + +use File::Basename; +use Memoize; +memoize 'wrong_wsrep_version'; +memoize 'check_garbd_support'; +memoize 'check_wsrep_support'; +memoize 'wsrep_not_ok'; + +use mtr_report; + +my $extra_path; +my $mariabackup_path; +my $mariabackup_exe; +my $garbd_exe; +my $file_wsrep_provider; + +sub wrong_wsrep_version() { + my $check_version= dirname($My::SafeProcess::safe_process_cmd[0]) . '/wsrep_check_version'; + my $checked = `$check_version -p`; + chomp($checked); + return $? ? $checked : undef; +} + +sub which($) { return `sh -c "command -v $_[0]"` } + +sub check_garbd_support() { + my $wsrep_path= dirname($file_wsrep_provider); + $garbd_exe= ::mtr_file_exists($wsrep_path."/garb/garbd", + $wsrep_path."/../../bin/garb/garbd", + '/usr/bin/garbd'); + $ENV{MTR_GARBD_EXE}= $garbd_exe if $garbd_exe; +} + +sub check_wsrep_support() { + mtr_report(" - binaries built with wsrep patch"); + + # ADD scripts to $PATH to that wsrep_sst_* can be found + my ($spath) = grep { -f "$_/wsrep_sst_rsync"; } "$::bindir/scripts", $::path_client_bindir; + mtr_error("No SST scripts") unless $spath; + $ENV{PATH}="$spath:$ENV{PATH}"; + + # ADD mysql client library path to path so that wsrep_notify_cmd can find mysql + # client for loading the tables. (Don't assume each machine has mysql install) + my ($cpath) = grep { -f "$_/mysql"; } "$::bindir/scripts", $::path_client_bindir; + mtr_error("No scritps") unless $cpath; + $ENV{PATH}="$cpath:$ENV{PATH}" unless $cpath eq $spath; + + # ADD my_print_defaults script path to path so that SST scripts can find it + my $my_print_defaults_exe= + ::mtr_exe_maybe_exists( + "$::bindir/extra/my_print_defaults", + "$::path_client_bindir/my_print_defaults"); + my $epath= ""; + if ($my_print_defaults_exe ne "") { + $epath= dirname($my_print_defaults_exe); + } + mtr_error("No my_print_defaults") unless $epath; + $ENV{PATH}="$epath:$ENV{PATH}" unless ($epath eq $spath) or + ($epath eq $cpath); + + $extra_path= $epath; + + if (which("socat")) { + $ENV{MTR_GALERA_TFMT}="socat"; + } elsif (which("nc")) { + $ENV{MTR_GALERA_TFMT}="nc"; + } + + $ENV{PATH}=dirname($ENV{XTRABACKUP}).":$ENV{PATH}" if $ENV{XTRABACKUP}; + + # Check whether WSREP_PROVIDER environment variable is set. + if (defined $ENV{'WSREP_PROVIDER'}) { + $file_wsrep_provider= ""; + if ($ENV{'WSREP_PROVIDER'} ne "none") { + if (::mtr_file_exists($ENV{'WSREP_PROVIDER'}) ne "") { + $file_wsrep_provider= $ENV{'WSREP_PROVIDER'}; + } else { + mtr_error("WSREP_PROVIDER env set to an invalid path"); + } + check_garbd_support(); + } + # WSREP_PROVIDER is valid; set to a valid path or "none"). + mtr_verbose("WSREP_PROVIDER env set to $ENV{'WSREP_PROVIDER'}"); + } else { + # WSREP_PROVIDER env not defined. Lets try to locate the wsrep provider + # library. + $file_wsrep_provider= + ::mtr_file_exists("/usr/lib64/galera-4/libgalera_smm.so", + "/usr/lib64/galera/libgalera_smm.so", + "/usr/lib/galera-4/libgalera_smm.so", + "/usr/lib/galera/libgalera_smm.so"); + if ($file_wsrep_provider ne "") { + # wsrep provider library found ! + mtr_verbose("wsrep provider library found : $file_wsrep_provider"); + $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; + check_garbd_support(); + } else { + mtr_verbose("Could not find wsrep provider library, setting it to 'none'"); + $ENV{'WSREP_PROVIDER'}= "none"; + } + } +} + +sub wsrep_not_ok() { + return "Not run for embedded server" if $::opt_embedded_server; + return "WSREP is not compiled in" if not $::mysqld_variables{'wsrep-on'}; + check_wsrep_support(); + return "No wsrep provider library" unless $file_wsrep_provider; + return wrong_wsrep_version() if wrong_wsrep_version(); + undef; +} + +1; diff --git a/mysql-test/suite/wsrep/suite.pm b/mysql-test/suite/wsrep/suite.pm index 7b3dae7c8c3..2ee33d83275 100644 --- a/mysql-test/suite/wsrep/suite.pm +++ b/mysql-test/suite/wsrep/suite.pm @@ -1,16 +1,11 @@ package My::Suite::WSREP; -use File::Basename; -use My::Find; + +use lib 'suite'; +use wsrep::common; @ISA = qw(My::Suite); -return "Not run for embedded server" if $::opt_embedded_server; - -return "WSREP is not compiled in" unless ::have_wsrep(); - -return "No wsrep provider library" unless ::have_wsrep_provider(); - -return ::wsrep_version_message() unless ::check_wsrep_version(); +return wsrep_not_ok() if wsrep_not_ok(); push @::global_suppressions, ( diff --git a/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm b/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm index 9170a337bf4..c7d4b0adf5b 100644 --- a/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm +++ b/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm @@ -4,15 +4,9 @@ use My::Find; @ISA = qw(My::Suite); -return "Not run for embedded server" if $::opt_embedded_server; - -return "WSREP is not compiled in" if not ::have_wsrep(); - -return "No wsrep provider library" unless ::have_wsrep_provider(); - -return ::wsrep_version_message() unless ::check_wsrep_version(); - -return "No WSREP_INFO plugin" unless $ENV{WSREP_INFO_SO}; +use lib 'suite'; +use wsrep::common; +return wsrep_not_ok() if wsrep_not_ok(); push @::global_suppressions, ( From b976b9bfc3ec12cf4dcf57da828c0315916c1413 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 21 Apr 2020 18:40:15 +0200 Subject: [PATCH 15/35] MDEV-21244 mysql_upgrade creating empty global_priv table support upgrades from 5.2 privilege tables --- mysql-test/main/mysql_upgrade.result | 8 ++++++++ mysql-test/main/mysql_upgrade.test | 13 +++++++++++++ scripts/mysql_system_tables_fix.sql | 1 + 3 files changed, 22 insertions(+) diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result index f71ce087ba1..862e7e8f3d4 100644 --- a/mysql-test/main/mysql_upgrade.result +++ b/mysql-test/main/mysql_upgrade.result @@ -630,4 +630,12 @@ drop table mysql.innodb_index_stats, mysql.innodb_table_stats; # mysql_upgrade --force --silent 2>&1 drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +drop view mysql.user_bak; +alter table mysql.user change authentication_string auth_string text collate utf8_bin not null; +# mysql_upgrade --force --silent 2>&1 +select count(*) from mysql.global_priv; +count(*) +4 +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; # End of 10.4 tests diff --git a/mysql-test/main/mysql_upgrade.test b/mysql-test/main/mysql_upgrade.test index 3dfe38701aa..0dad53f8881 100644 --- a/mysql-test/main/mysql_upgrade.test +++ b/mysql-test/main/mysql_upgrade.test @@ -282,4 +282,17 @@ drop table mysql.innodb_index_stats, mysql.innodb_table_stats; drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# +# MDEV-21244 mysql_upgrade creating empty global_priv table +# +--source include/switch_to_mysql_user.inc +drop view mysql.user_bak; +alter table mysql.user change authentication_string auth_string text collate utf8_bin not null; +--echo # mysql_upgrade --force --silent 2>&1 +--exec $MYSQL_UPGRADE --force --silent 2>&1 +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info +select count(*) from mysql.global_priv; +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; + --echo # End of 10.4 tests diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 741b814b83a..8faf7bcaf14 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -648,6 +648,7 @@ UPDATE user SET Delete_history_priv = Super_priv WHERE @had_user_delete_history_ ALTER TABLE user ADD plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, ADD authentication_string TEXT NOT NULL; +ALTER TABLE user CHANGE auth_string authentication_string TEXT NOT NULL; ALTER TABLE user MODIFY plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, MODIFY authentication_string TEXT NOT NULL; ALTER TABLE user ADD password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; From 2144dc1ff2916ba1c0b0fded9cb7022b9ecf47a9 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 21 Apr 2020 18:45:12 +0200 Subject: [PATCH 16/35] more verbose tests --- mysql-test/include/switch_to_mysql_global_priv.inc | 1 + mysql-test/include/switch_to_mysql_user.inc | 1 + mysql-test/main/connect.result | 4 ++++ mysql-test/main/empty_user_table.result | 2 ++ mysql-test/main/grant.result | 2 ++ mysql-test/main/grant4.result | 4 ++++ mysql-test/main/grant_4332.result | 2 ++ mysql-test/main/mysql_upgrade.result | 4 ++++ mysql-test/main/mysql_upgrade_noengine.result | 3 +++ mysql-test/main/password_expiration.result | 2 ++ mysql-test/main/plugin_auth.result | 1 + mysql-test/main/set_password.result | 2 ++ mysql-test/main/sp_notembedded.result | 4 ++++ mysql-test/main/system_mysql_db_507.result | 2 ++ mysql-test/suite/plugins/r/multiauth.result | 2 ++ .../roles/create_and_drop_role_invalid_user_table.result | 2 ++ 16 files changed, 38 insertions(+) diff --git a/mysql-test/include/switch_to_mysql_global_priv.inc b/mysql-test/include/switch_to_mysql_global_priv.inc index 78df6642760..3a93746c4e8 100644 --- a/mysql-test/include/switch_to_mysql_global_priv.inc +++ b/mysql-test/include/switch_to_mysql_global_priv.inc @@ -1,3 +1,4 @@ +echo # switching back from mysql.user to mysql.global_priv; disable_query_log; drop table mysql.user; rename table mysql.user_bak to mysql.user; diff --git a/mysql-test/include/switch_to_mysql_user.inc b/mysql-test/include/switch_to_mysql_user.inc index 4d67f30a10b..7e5e460390c 100644 --- a/mysql-test/include/switch_to_mysql_user.inc +++ b/mysql-test/include/switch_to_mysql_user.inc @@ -1,3 +1,4 @@ +echo # switching from mysql.global_priv to mysql.user; disable_query_log; rename table mysql.user to mysql.user_bak; CREATE TABLE mysql.user ( diff --git a/mysql-test/main/connect.result b/mysql-test/main/connect.result index ee1844bc3ee..229c2d9dafe 100644 --- a/mysql-test/main/connect.result +++ b/mysql-test/main/connect.result @@ -99,6 +99,7 @@ ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) connect(localhost,test,zorro,test,MASTER_PORT,MASTER_SOCKET); connect fail_con,localhost,test,zorro,; ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) +# switching from mysql.global_priv to mysql.user update mysql.user set plugin="", authentication_string="", password=old_password("gambling2") where user=_binary"test"; flush privileges; show grants for test@localhost; @@ -168,6 +169,7 @@ ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) connect(localhost,test,zorro,test,MASTER_PORT,MASTER_SOCKET); connect fail_con,localhost,test,zorro,; ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) +# switching back from mysql.user to mysql.global_priv delete from mysql.user where user=_binary"test"; connect con7,localhost,root,,test; create table t1 (id integer not null auto_increment primary key); @@ -363,6 +365,7 @@ connect(localhost,mysqltest_nouser,,test,MASTER_PORT,MASTER_SOCKET); connect pcon5,localhost,mysqltest_nouser,,,$MASTER_MYPORT,; ERROR 28000: Access denied for user 'mysqltest_nouser'@'localhost' (using password: NO) connection default; +# switching from mysql.global_priv to mysql.user update mysql.user set plugin='mysql_native_password' where user = 'mysqltest_up1'; update mysql.user set plugin='mysql_old_password' where user = 'mysqltest_up2'; select user, password, plugin, authentication_string from mysql.user @@ -382,6 +385,7 @@ user() current_user() mysqltest_up2@localhost mysqltest_up2@% disconnect pcon7; connection default; +# switching back from mysql.user to mysql.global_priv DROP USER mysqltest_up1@'%'; DROP USER mysqltest_up2@'%'; # diff --git a/mysql-test/main/empty_user_table.result b/mysql-test/main/empty_user_table.result index 924e4cd8ea5..e5307c36e24 100644 --- a/mysql-test/main/empty_user_table.result +++ b/mysql-test/main/empty_user_table.result @@ -7,8 +7,10 @@ Got one of the listed errors insert mysql.global_priv select * from t1; drop table t1; flush privileges; +# switching from mysql.global_priv to mysql.user truncate table mysql.user; flush privileges; connect(localhost,u1,,test,MASTER_PORT,MASTER_SOCKET); connect fail,localhost,u1; Got one of the listed errors +# switching back from mysql.user to mysql.global_priv diff --git a/mysql-test/main/grant.result b/mysql-test/main/grant.result index 5d4fdabfd41..3d2313e8c9b 100644 --- a/mysql-test/main/grant.result +++ b/mysql-test/main/grant.result @@ -2757,6 +2757,7 @@ DROP USER dummy@localhost; # # MDEV-19948 'show grants' return privileges individually # +# switching from mysql.global_priv to mysql.user CREATE USER ten2; GRANT ALL ON *.* TO ten2; SHOW GRANTS FOR ten2; @@ -2767,6 +2768,7 @@ SHOW GRANTS FOR ten2; Grants for ten2@% GRANT ALL PRIVILEGES ON *.* TO `ten2`@`%` DROP USER ten2; +# switching back from mysql.user to mysql.global_priv # # End of 10.3 tests # diff --git a/mysql-test/main/grant4.result b/mysql-test/main/grant4.result index 9da0b0b40b7..f252a4c2ad5 100644 --- a/mysql-test/main/grant4.result +++ b/mysql-test/main/grant4.result @@ -129,6 +129,7 @@ connection default; disconnect con1; drop database mysqltest_db1; drop user mysqltest_u1@localhost; +# switching from mysql.global_priv to mysql.user call mtr.add_suppression("Table 'mysql.user' doesn't exist"); call mtr.add_suppression("'mysql.user' is not of type 'TABLE'"); rename table mysql.user to mysql.user1; @@ -141,6 +142,8 @@ flush privileges; ERROR 42S02: Table 'mysql.user' doesn't exist drop temporary table mysql.user; rename table mysql.user1 to mysql.user; +# switching back from mysql.user to mysql.global_priv +# switching from mysql.global_priv to mysql.user call mtr.add_suppression('mysql.user table is damaged'); rename table mysql.user to mysql.user1; create table mysql.user (Host char(100), User char(100)); @@ -148,6 +151,7 @@ flush privileges; ERROR HY000: Unknown error drop table mysql.user; rename table mysql.user1 to mysql.user; +# switching back from mysql.user to mysql.global_priv End of 5.5 tests # # Additional coverage for refactoring which is made as part diff --git a/mysql-test/main/grant_4332.result b/mysql-test/main/grant_4332.result index af6b23088f5..7fc29795b6f 100644 --- a/mysql-test/main/grant_4332.result +++ b/mysql-test/main/grant_4332.result @@ -1,3 +1,4 @@ +# switching from mysql.global_priv to mysql.user set global sql_mode=""; set local sql_mode=""; alter table mysql.user modify User char(16) binary not null default ''; @@ -33,3 +34,4 @@ def user() 253 141 14 N 1 39 8 user() root@localhost set global sql_mode=default; +# switching back from mysql.user to mysql.global_priv diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result index 862e7e8f3d4..33c3d1b8198 100644 --- a/mysql-test/main/mysql_upgrade.result +++ b/mysql-test/main/mysql_upgrade.result @@ -575,6 +575,7 @@ SET GLOBAL enforce_storage_engine=NULL; # Ensure that mysql_upgrade correctly sets truncate_versioning_priv # on upgrade from 10.2 # +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; CREATE USER 'user3'@'%'; GRANT USAGE ON *.* TO 'user3'@'%'; @@ -593,6 +594,7 @@ update mysql.db set Delete_history_priv='Y' where db like 'test%'; drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; # End of 10.3 tests +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; create user 'user3'@'localhost' identified with mysql_native_password as password('a_password'); show create user user3@localhost; @@ -625,11 +627,13 @@ connection default; drop user user3@localhost; drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; drop table mysql.innodb_index_stats, mysql.innodb_table_stats; # mysql_upgrade --force --silent 2>&1 drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; alter table mysql.user change authentication_string auth_string text collate utf8_bin not null; # mysql_upgrade --force --silent 2>&1 diff --git a/mysql-test/main/mysql_upgrade_noengine.result b/mysql-test/main/mysql_upgrade_noengine.result index 79ad04e1849..7b7082ab007 100644 --- a/mysql-test/main/mysql_upgrade_noengine.result +++ b/mysql-test/main/mysql_upgrade_noengine.result @@ -1,3 +1,4 @@ +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; install soname 'ha_blackhole'; install soname 'ha_archive'; @@ -144,6 +145,7 @@ Code 1286 Message Unknown storage engine 'ARCHIVE' drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; alter table mysql.user drop column default_role, drop column max_statement_time; Phase 1/7: Checking and upgrading mysql database @@ -236,6 +238,7 @@ Code 1286 Message Unknown storage engine 'ARCHIVE' drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; alter table mysql.user drop column default_role, drop column max_statement_time; Phase 1/7: Checking and upgrading mysql database diff --git a/mysql-test/main/password_expiration.result b/mysql-test/main/password_expiration.result index bb39d8788dc..d05f6b3b5d0 100644 --- a/mysql-test/main/password_expiration.result +++ b/mysql-test/main/password_expiration.result @@ -138,6 +138,7 @@ ERROR HY000: Incorrect DAY value: '0' # # Password expiration fields are loaded properly on 10.3 tables # +# switching from mysql.global_priv to mysql.user create user user1@localhost; show create user user1@localhost; CREATE USER for user1@localhost @@ -205,6 +206,7 @@ connection default; drop user user1@localhost; set global disconnect_on_expired_password=default; set global default_password_lifetime=default; +# switching back from mysql.user to mysql.global_priv # # PASSWORD EXPIRE DEFAULT should use the default_password_lifetime # system var to set the number of days till expiration diff --git a/mysql-test/main/plugin_auth.result b/mysql-test/main/plugin_auth.result index 244e048c517..73c384734bd 100644 --- a/mysql-test/main/plugin_auth.result +++ b/mysql-test/main/plugin_auth.result @@ -354,6 +354,7 @@ uplain@localhost uplain@localhost connection default; disconnect cleartext_con; DROP USER uplain@localhost; +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; # # Bug #59038 : mysql.user.authentication_string column diff --git a/mysql-test/main/set_password.result b/mysql-test/main/set_password.result index eef7c6eccea..91c8b567ad6 100644 --- a/mysql-test/main/set_password.result +++ b/mysql-test/main/set_password.result @@ -158,6 +158,7 @@ connection default; drop user natauth@localhost, newpass@localhost, newpassnat@localhost; drop user oldauth@localhost, oldpass@localhost, oldpassold@localhost; set global secure_auth=default; +# switching from mysql.global_priv to mysql.user create user foo@localhost identified with mysql_native_password; update mysql.user set authentication_string=password('foo'), plugin='mysql_native_password' where user='foo' and host='localhost'; set password for 'foo'@'localhost' = password('bar'); @@ -179,3 +180,4 @@ select user,host,password,plugin,authentication_string from mysql.user where use user host password plugin authentication_string foo localhost mysql_native_password drop user foo@localhost; +# switching back from mysql.user to mysql.global_priv diff --git a/mysql-test/main/sp_notembedded.result b/mysql-test/main/sp_notembedded.result index 3cf066f5b4c..e03361598a6 100644 --- a/mysql-test/main/sp_notembedded.result +++ b/mysql-test/main/sp_notembedded.result @@ -212,6 +212,7 @@ disconnect rl_contender; drop procedure p1; drop table t1; set session low_priority_updates=default; +# switching from mysql.global_priv to mysql.user INSERT IGNORE INTO mysql.user (Host, User, Password, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv, Reload_priv, Shutdown_priv, Process_priv, File_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Show_db_priv, Super_priv, @@ -231,6 +232,7 @@ CREATE PROCEDURE p1(i INT) BEGIN END; disconnect con1; connection default; DROP PROCEDURE p1; +# switching back from mysql.user to mysql.global_priv # # Bug#44521 Prepared Statement: CALL p() - crashes: `! thd->main_da.is_sent' failed et.al. # @@ -323,6 +325,7 @@ DROP EVENT teste_bug11763507; # ------------------------------------------------------------------ # -- End of 5.1 tests # ------------------------------------------------------------------ +# switching from mysql.global_priv to mysql.user grant create routine on test.* to foo1@localhost identified by 'foo'; update mysql.user set authentication_string = replace(authentication_string, '*', '-') where user='foo1'; connect foo,localhost,foo1,foo; @@ -347,4 +350,5 @@ connection default; disconnect foo; drop procedure spfoo; drop user foo1@localhost; +# switching back from mysql.user to mysql.global_priv set @@global.concurrent_insert= @old_concurrent_insert; diff --git a/mysql-test/main/system_mysql_db_507.result b/mysql-test/main/system_mysql_db_507.result index 00b53a5798d..2d68dc82529 100644 --- a/mysql-test/main/system_mysql_db_507.result +++ b/mysql-test/main/system_mysql_db_507.result @@ -3,6 +3,7 @@ # Fatal error: mysql.user table is damaged or in # unsupported 3.20 format # +# switching from mysql.global_priv to mysql.user # # Original mysql.user table # @@ -221,3 +222,4 @@ drop user user@localhost; # # Reset to final original state. # +# switching back from mysql.user to mysql.global_priv diff --git a/mysql-test/suite/plugins/r/multiauth.result b/mysql-test/suite/plugins/r/multiauth.result index 4b9a603867c..a62532e3225 100644 --- a/mysql-test/suite/plugins/r/multiauth.result +++ b/mysql-test/suite/plugins/r/multiauth.result @@ -152,8 +152,10 @@ show create user mysqltest1; CREATE USER for mysqltest1@% CREATE USER `mysqltest1`@`%` IDENTIFIED VIA mysql_native_password USING '*BFE3F4604CFD21E6595080A261D92EF0183B5971' OR unix_socket drop user mysqltest1; +# switching from mysql.global_priv to mysql.user create user mysqltest1 identified via ed25519 as password("good") OR unix_socket OR mysql_native_password as password("works"); ERROR HY000: Column count of mysql.user is wrong. Expected 3, found 47. Created with MariaDB XX.YY.ZZ, now running XX.YY.ZZ. Please use mysql_upgrade to fix this error +# switching back from mysql.user to mysql.global_priv create user USER identified via mysql_native_password as '1234567890123456789012345678901234567890a' OR unix_socket; create user mysqltest1 identified via mysql_native_password as '1234567890123456789012345678901234567890a' OR unix_socket; update mysql.global_priv set priv=replace(priv, '1234567890123456789012345678901234567890a', 'invalid password'); diff --git a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result index 5902ae0e16c..412ddf9d423 100644 --- a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result +++ b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result @@ -1,3 +1,4 @@ +# switching from mysql.global_priv to mysql.user connect mysql, localhost, root,,; use mysql; alter table user drop column is_role; @@ -26,3 +27,4 @@ update user set is_role='N'; flush privileges; create role test_role; drop role test_role; +# switching back from mysql.user to mysql.global_priv From a58b2b3b2b564bff9a521c90ab23f850ee9888d3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 22 Apr 2020 19:59:48 +0200 Subject: [PATCH 17/35] MDEV-21928 ALTER USER doesn't remove excess authentication plugins from mysql.global_priv only use auth1 update (no "auth_or":[]) array, if there was no "auth_or" array in the json yet. --- mysql-test/suite/plugins/r/multiauth.result | 13 +++++++++++++ mysql-test/suite/plugins/t/multiauth.test | 11 +++++++++++ sql/sql_acl.cc | 7 +++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/plugins/r/multiauth.result b/mysql-test/suite/plugins/r/multiauth.result index a62532e3225..7b6465c3040 100644 --- a/mysql-test/suite/plugins/r/multiauth.result +++ b/mysql-test/suite/plugins/r/multiauth.result @@ -193,3 +193,16 @@ user() current_user() database() mysqltest1@localhost mysqltest1@% test drop user mysqltest1; uninstall soname 'auth_ed25519'; +create user mysqltest1 identified via mysql_native_password as password("good") OR unix_socket; +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER `mysqltest1`@`%` IDENTIFIED VIA mysql_native_password USING '*8409037B3E362D6DAE24C8E667F4D3B66716144E' OR unix_socket +alter user mysqltest1 identified via mysql_native_password as password("better"); +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER `mysqltest1`@`%` IDENTIFIED BY PASSWORD '*6E6CABC9967AB586F009616BA69DAC2953849C88' +flush privileges; +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER `mysqltest1`@`%` IDENTIFIED BY PASSWORD '*6E6CABC9967AB586F009616BA69DAC2953849C88' +drop user mysqltest1; diff --git a/mysql-test/suite/plugins/t/multiauth.test b/mysql-test/suite/plugins/t/multiauth.test index ffd4851c20d..cc6fc0c8644 100644 --- a/mysql-test/suite/plugins/t/multiauth.test +++ b/mysql-test/suite/plugins/t/multiauth.test @@ -194,3 +194,14 @@ drop user mysqltest1; uninstall soname 'auth_ed25519'; --remove_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt + +# +# MDEV-21928 ALTER USER doesn't remove excess authentication plugins from mysql.global_priv +# +create user mysqltest1 identified via mysql_native_password as password("good") OR unix_socket; +show create user mysqltest1; +alter user mysqltest1 identified via mysql_native_password as password("better"); +show create user mysqltest1; +flush privileges; +show create user mysqltest1; +drop user mysqltest1; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index d210403a269..6f403d9ade6 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1425,9 +1425,12 @@ class User_table_json: public User_table bool set_auth(const ACL_USER &u) const { - StringBuffer json(m_table->field[2]->charset()); - if (u.nauth == 1) + size_t array_len; + const char *array; + if (u.nauth == 1 && get_value("auth_or", JSV_ARRAY, &array, &array_len)) return set_auth1(u, 0); + + StringBuffer json(m_table->field[2]->charset()); bool top_done = false; json.append('['); for (uint i=0; i < u.nauth; i++) From 6dab094fbd31ef93a1d51b1b9c867188b2f958c3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 25 Apr 2020 12:49:47 +0200 Subject: [PATCH 18/35] MDEV-20257 Server crashes in Grant_table_base::init_read_record upon crash-upgrade when opening the `user` table separately, reset `thd->open_tables` for the duration of open, otherwise auto-repair fallback-and-retry will close *all* tables (but reopen only `user`) --- mysql-test/main/grant_repair.result | 9 +++++++++ mysql-test/main/grant_repair.test | 19 +++++++++++++++++++ sql/sql_acl.cc | 11 ++++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 mysql-test/main/grant_repair.result create mode 100644 mysql-test/main/grant_repair.test diff --git a/mysql-test/main/grant_repair.result b/mysql-test/main/grant_repair.result new file mode 100644 index 00000000000..afadca78db7 --- /dev/null +++ b/mysql-test/main/grant_repair.result @@ -0,0 +1,9 @@ +call mtr.add_suppression("/mysql/user"); +# switching from mysql.global_priv to mysql.user +flush tables; +flush privileges; +Warnings: +Error 145 Table './mysql/user' is marked as crashed and should be repaired +Warning 1034 12544 clients are using or haven't closed the table properly +Note 1034 Table is fixed +# switching back from mysql.user to mysql.global_priv diff --git a/mysql-test/main/grant_repair.test b/mysql-test/main/grant_repair.test new file mode 100644 index 00000000000..0fc0edc7ded --- /dev/null +++ b/mysql-test/main/grant_repair.test @@ -0,0 +1,19 @@ +# +# MDEV-20257 Server crashes in Grant_table_base::init_read_record upon crash-upgrade +# + +call mtr.add_suppression("/mysql/user"); +source include/switch_to_mysql_user.inc; + +let mysql_datadir=`select @@datadir`; +flush tables; +perl; + $f=$ENV{mysql_datadir} . '/mysql/user.MAI'; + sysopen F, $f, 2 or die "sysopen $f: $!"; + # set the open_count to 1, "table was not closed properly" + sysseek F, 24, O_RDWR or die "sysseek: $!"; + syswrite F, 1, 1 or die "syswrite: $!"; +EOF +flush privileges; + +source include/switch_to_mysql_global_priv.inc; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 6f403d9ade6..699bd4e3cbc 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1847,10 +1847,13 @@ class Grant_tables int res= really_open(thd, first, &counter); /* if User_table_json wasn't found, let's try User_table_tabular */ - if (!res && (which_tables & Table_user) && !(tables[USER_TABLE].table)) + if (!res && (which_tables & Table_user) && !tables[USER_TABLE].table) { uint unused; TABLE_LIST *tl= tables + USER_TABLE; + TABLE *backup_open_tables= thd->open_tables; + thd->set_open_tables(NULL); + tl->init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLE_NAME_USER, NULL, lock_type); tl->open_type= OT_BASE_ONLY; @@ -1859,6 +1862,12 @@ class Grant_tables p_user_table= &m_user_table_tabular; counter++; res= really_open(thd, tl, &unused); + thd->set_open_tables(backup_open_tables); + if (tables[USER_TABLE].table) + { + tables[USER_TABLE].table->next= backup_open_tables; + thd->set_open_tables(tables[USER_TABLE].table); + } } if (res) DBUG_RETURN(res); From edbdfc2f995eb47ba49235195aca00888aeacbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 27 Apr 2020 11:18:11 +0300 Subject: [PATCH 19/35] MDEV-7962 wsrep_on() takes 0.14% in OLTP RO The function wsrep_on() was being called rather frequently in InnoDB and XtraDB. Let us cache it in trx_t and invoke trx_t::is_wsrep() instead. innobase_trx_init(): Cache trx->wsrep = wsrep_on(thd). ha_innobase::write_row(): Replace many repeated calls to current_thd, and test the cheapest condition first. --- storage/innobase/handler/ha_innodb.cc | 111 +++++++++-------------- storage/innobase/include/lock0lock.h | 5 +- storage/innobase/include/trx0trx.h | 14 ++- storage/innobase/lock/lock0lock.cc | 13 ++- storage/innobase/lock/lock0wait.cc | 7 +- storage/innobase/row/row0ins.cc | 4 +- storage/innobase/row/row0mysql.cc | 2 +- storage/innobase/row/row0upd.cc | 4 +- storage/innobase/srv/srv0conc.cc | 11 +-- storage/innobase/trx/trx0trx.cc | 8 +- storage/xtradb/handler/ha_innodb.cc | 126 +++++++++++--------------- storage/xtradb/include/lock0lock.h | 3 +- storage/xtradb/include/trx0trx.h | 14 ++- storage/xtradb/lock/lock0lock.cc | 13 ++- storage/xtradb/lock/lock0wait.cc | 7 +- storage/xtradb/row/row0ins.cc | 4 +- storage/xtradb/row/row0upd.cc | 4 +- storage/xtradb/srv/srv0conc.cc | 11 +-- storage/xtradb/trx/trx0roll.cc | 11 +-- storage/xtradb/trx/trx0trx.cc | 8 +- 20 files changed, 160 insertions(+), 220 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 4de2cdbeaec..f9bad3a128c 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2019, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1671,8 +1671,7 @@ innobase_srv_conc_enter_innodb( trx_t* trx) /*!< in: transaction handle */ { #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; + if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; #endif /* WITH_WSREP */ if (srv_thread_concurrency) { if (trx->n_tickets_to_enter_innodb > 0) { @@ -1710,8 +1709,7 @@ innobase_srv_conc_exit_innodb( ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch)); #endif /* UNIV_SYNC_DEBUG */ #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; + if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; #endif /* WITH_WSREP */ /* This is to avoid making an unnecessary function call. */ @@ -2638,6 +2636,9 @@ innobase_trx_init( trx->check_unique_secondary = !thd_test_options( thd, OPTION_RELAXED_UNIQUE_CHECKS); +#ifdef WITH_WSREP + trx->wsrep = wsrep_on(thd); +#endif DBUG_VOID_RETURN; } @@ -4185,19 +4186,17 @@ innobase_commit_low( trx_t* trx) /*!< in: transaction handle */ { #ifdef WITH_WSREP - THD* thd = (THD*)trx->mysql_thd; const char* tmp = 0; - if (thd && wsrep_on(thd)) { + if (trx->is_wsrep()) { #ifdef WSREP_PROC_INFO char info[64]; info[sizeof(info) - 1] = '\0'; snprintf(info, sizeof(info) - 1, "innobase_commit_low():trx_commit_for_mysql(%lld)", - (long long) wsrep_thd_trx_seqno(thd)); - tmp = thd_proc_info(thd, info); - + (long long) wsrep_thd_trx_seqno(trx->mysql_thd)); + tmp = thd_proc_info(trx->mysql_thd, info); #else - tmp = thd_proc_info(thd, "innobase_commit_low()"); + tmp = thd_proc_info(trx->mysql_thd, "innobase_commit_low()"); #endif /* WSREP_PROC_INFO */ } #endif /* WITH_WSREP */ @@ -4206,7 +4205,7 @@ innobase_commit_low( trx_commit_for_mysql(trx); } #ifdef WITH_WSREP - if (thd && wsrep_on(thd)) { thd_proc_info(thd, tmp); } + if (trx->is_wsrep()) { thd_proc_info(trx->mysql_thd, tmp); } #endif /* WITH_WSREP */ } @@ -8151,19 +8150,19 @@ ha_innobase::write_row( sql_command = thd_sql_command(user_thd); - if ((sql_command == SQLCOM_ALTER_TABLE - || sql_command == SQLCOM_OPTIMIZE - || sql_command == SQLCOM_CREATE_INDEX + if (num_write_row >= 10000 + && (sql_command == SQLCOM_ALTER_TABLE + || sql_command == SQLCOM_OPTIMIZE + || sql_command == SQLCOM_CREATE_INDEX #ifdef WITH_WSREP - || (wsrep_on(user_thd) && wsrep_load_data_splitting && - sql_command == SQLCOM_LOAD && - !thd_test_options( - user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + || (sql_command == SQLCOM_LOAD && + trx->is_wsrep() && wsrep_load_data_splitting && + !thd_test_options( + user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) #endif /* WITH_WSREP */ - || sql_command == SQLCOM_DROP_INDEX) - && num_write_row >= 10000) { + || sql_command == SQLCOM_DROP_INDEX)) { #ifdef WITH_WSREP - if (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) { + if (sql_command == SQLCOM_LOAD && trx->is_wsrep()) { WSREP_DEBUG("forced trx split for LOAD: %s", wsrep_thd_query(user_thd)); } @@ -8202,9 +8201,8 @@ no_commit: ; } else if (src_table == prebuilt->table) { #ifdef WITH_WSREP - if (wsrep_on(user_thd) && - wsrep_load_data_splitting && - sql_command == SQLCOM_LOAD && + if (sql_command == SQLCOM_LOAD && trx->is_wsrep() && + wsrep_load_data_splitting && !thd_test_options(user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { @@ -8234,9 +8232,8 @@ no_commit: prebuilt->sql_stat_start = TRUE; } else { #ifdef WITH_WSREP - if (wsrep_on(user_thd) && - wsrep_load_data_splitting && - sql_command == SQLCOM_LOAD && + if (sql_command == SQLCOM_LOAD && trx->is_wsrep() && + wsrep_load_data_splitting && !thd_test_options(user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { @@ -8377,21 +8374,19 @@ no_commit: prebuilt->autoinc_offset, prebuilt->autoinc_increment); - if (wsrep_on(current_thd) && + if (trx->is_wsrep() && auto_inc_inserted && wsrep_drupal_282555_workaround && - wsrep_thd_retry_counter(current_thd) == 0 && - !thd_test_options(current_thd, + wsrep_thd_retry_counter(user_thd) == 0 && + !thd_test_options(user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { WSREP_DEBUG( "retrying insert: %s", - (*wsrep_thd_query(current_thd)) ? - wsrep_thd_query(current_thd) : - (char *)"void"); + wsrep_thd_query(user_thd)); error= DB_SUCCESS; wsrep_thd_set_conflict_state( - current_thd, MUST_ABORT); + user_thd, MUST_ABORT); innobase_srv_conc_exit_innodb(prebuilt->trx); /* jump straight to func exit over * later wsrep hooks */ @@ -8429,7 +8424,7 @@ set_max_autoinc: prebuilt autoinc values don't get properly assigned. Fetch values from server side. */ - if (wsrep_on(user_thd) && + if (trx->is_wsrep() && wsrep_thd_exec_mode(user_thd) == REPL_RECV) { wsrep_thd_auto_increment_variables( @@ -8478,8 +8473,7 @@ report_error: user_thd); #ifdef WITH_WSREP - if (!error_result - && wsrep_on(user_thd) + if (!error_result && trx->is_wsrep() && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && !wsrep_consistency_check(user_thd) && !wsrep_thd_ignore_table(user_thd)) { @@ -8487,10 +8481,9 @@ report_error: NULL)) { DBUG_PRINT("wsrep", ("row key failed")); error_result = HA_ERR_INTERNAL_ERROR; - goto wsrep_error; + goto func_exit; } } -wsrep_error: #endif /* WITH_WSREP */ if (error_result == HA_FTS_INVALID_DOCID) { @@ -8973,7 +8966,7 @@ ha_innobase::update_row( prebuilt autoinc values don't get properly assigned. Fetch values from server side. */ - if (wsrep_on(user_thd) && + if (trx->is_wsrep() && wsrep_thd_exec_mode(user_thd) == REPL_RECV) { wsrep_thd_auto_increment_variables( @@ -9018,9 +9011,8 @@ func_exit: innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS && + if (error == DB_SUCCESS && trx->is_wsrep() && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && - wsrep_on(user_thd) && !wsrep_thd_ignore_table(user_thd)) { DBUG_PRINT("wsrep", ("update row key")); @@ -9029,14 +9021,11 @@ func_exit: new_row)) { WSREP_DEBUG("WSREP: UPDATE_ROW_KEY FAILED"); DBUG_PRINT("wsrep", ("row key failed")); - err = HA_ERR_INTERNAL_ERROR; - goto wsrep_error; + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } } -wsrep_error: #endif /* WITH_WSREP */ - DBUG_RETURN(err); } @@ -9085,19 +9074,16 @@ ha_innobase::delete_row( innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS && + if (error == DB_SUCCESS && trx->is_wsrep() && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && - wsrep_on(user_thd) && !wsrep_thd_ignore_table(user_thd)) { if (wsrep_append_keys(user_thd, WSREP_KEY_EXCLUSIVE, record, NULL)) { DBUG_PRINT("wsrep", ("delete fail")); - error = (dberr_t) HA_ERR_INTERNAL_ERROR; - goto wsrep_error; + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } } -wsrep_error: #endif /* WITH_WSREP */ DBUG_RETURN(convert_error_code_to_mysql( error, prebuilt->table->flags, user_thd)); @@ -10370,8 +10356,7 @@ wsrep_append_foreign_key( int cache_key_len; bool const copy = true; - if (!wsrep_on(trx->mysql_thd) || - wsrep_thd_exec_mode(thd) != LOCAL_STATE) + if (!trx->is_wsrep() || wsrep_thd_exec_mode(thd) != LOCAL_STATE) return DB_SUCCESS; if (!thd || !foreign || @@ -14921,12 +14906,11 @@ ha_innobase::external_lock( THD* thd, /*!< in: handle to the user thread */ int lock_type) /*!< in: lock type */ { - trx_t* trx; - DBUG_ENTER("ha_innobase::external_lock"); DBUG_PRINT("enter",("lock_type: %d", lock_type)); update_thd(thd); + trx_t* trx = prebuilt->trx; /* Statement based binlogging does not work in isolation level READ UNCOMMITTED and READ COMMITTED since the necessary @@ -14940,22 +14924,19 @@ ha_innobase::external_lock( && thd_binlog_format(thd) == BINLOG_FORMAT_STMT && thd_binlog_filter_ok(thd) && thd_sqlcom_can_generate_row_events(thd)) { - bool skip = 0; + bool skip = false; +#ifdef WITH_WSREP + skip = trx->is_wsrep() + && wsrep_thd_exec_mode(thd) != LOCAL_STATE; +#endif /* WITH_WSREP */ /* used by test case */ DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = true;); if (!skip) { -#ifdef WITH_WSREP - if (!wsrep_on(thd) || wsrep_thd_exec_mode(thd) == LOCAL_STATE) - { -#endif /* WITH_WSREP */ my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), " InnoDB is limited to row-logging when " "transaction isolation level is " "READ COMMITTED or READ UNCOMMITTED."); DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE); -#ifdef WITH_WSREP - } -#endif /* WITH_WSREP */ } } @@ -14986,8 +14967,6 @@ ha_innobase::external_lock( } - trx = prebuilt->trx; - prebuilt->sql_stat_start = TRUE; prebuilt->hint_need_to_fetch_extra_cols = 0; diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 2628cdfc461..d1ad4c403d4 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1008,10 +1009,6 @@ std::string lock_get_info( const lock_t*); -/*******************************************************************//** -@return whether wsrep_on is true on trx->mysql_thd*/ -#define wsrep_on_trx(trx) ((trx)->mysql_thd && wsrep_on((trx)->mysql_thd)) - #endif /* WITH_WSREP */ #ifndef UNIV_NONINL #include "lock0lock.ic" diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 0291140a982..9aa3daea4e1 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2019, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -769,15 +769,21 @@ struct trx_t{ ro_trx_list the first time they try to acquire a lock ie. by default we treat all read-only transactions as non-locking. */ trx_state_t state; - trx_lock_t lock; /*!< Information about the transaction locks and state. Protected by trx->mutex or lock_sys->mutex or both */ - ulint is_recovered; /*!< 0=normal transaction, - 1=recovered, must be rolled back, + bool is_recovered; /*!< false=normal transaction, + true=recovered, must be rolled back, protected by trx_sys->mutex when trx->in_rw_trx_list holds */ +#ifdef WITH_WSREP + /** whether wsrep_on(mysql_thd) held at the start of transaction */ + bool wsrep; + bool is_wsrep() const { return UNIV_UNLIKELY(wsrep); } +#else /* WITH_WSREP */ + bool is_wsrep() const { return false; } +#endif /* WITH_WSREP */ /* These fields are not protected by any mutex. */ const char* op_info; /*!< English text describing the diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 0fade62e7aa..0c4e40067d1 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2019, MariaDB Corporation. +Copyright (c) 2014, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1759,7 +1759,7 @@ wsrep_kill_victim( ut_ad(trx_mutex_own(lock->trx)); /* quit for native mysql */ - if (!wsrep_on(trx->mysql_thd)) return; + if (!trx->is_wsrep()) return; my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE); my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE); @@ -1845,7 +1845,7 @@ lock_rec_other_has_conflicting( #ifdef WITH_WSREP if (lock_rec_has_to_wait(TRUE, trx, mode, lock, is_supremum)) { - if (wsrep_on_trx(trx)) { + if (trx->is_wsrep()) { trx_mutex_enter(lock->trx); /* Below function will roll back either trx or lock->trx depending on priority of the @@ -2179,8 +2179,7 @@ lock_rec_create( ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted); #ifdef WITH_WSREP - if (c_lock && - wsrep_on_trx(trx) && + if (c_lock && trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { lock_t *hash = (lock_t *)c_lock->hash; lock_t *prev = NULL; @@ -4973,7 +4972,7 @@ lock_table_create( UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock); #ifdef WITH_WSREP - if (c_lock && wsrep_on_trx(trx)) { + if (c_lock && trx->is_wsrep()) { if (wsrep_thd_is_wsrep(trx->mysql_thd) && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { UT_LIST_INSERT_AFTER( @@ -5212,7 +5211,7 @@ lock_table_enqueue_waiting( /* Enqueue the lock request that will wait to be granted */ #ifdef WITH_WSREP - if (trx->lock.was_chosen_as_deadlock_victim && wsrep_on_trx(trx)) { + if (trx->lock.was_chosen_as_deadlock_victim && trx->is_wsrep()) { return(DB_DEADLOCK); } diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc index ca697ab8be5..8f39c555c6a 100644 --- a/storage/innobase/lock/lock0wait.cc +++ b/storage/innobase/lock/lock0wait.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2019, MariaDB Corporation. +Copyright (c) 2014, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -200,8 +200,7 @@ wsrep_is_BF_lock_timeout( const trx_t* trx, bool locked = true) { - if (wsrep_on_trx(trx) - && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { fprintf(stderr, "WSREP: BF lock wait long for trx " TRX_ID_FMT "\n", trx->id); srv_print_innodb_monitor = TRUE; srv_print_innodb_lock_monitor = TRUE; @@ -390,7 +389,7 @@ lock_wait_suspend_thread( if (lock_wait_timeout < 100000000 && wait_time > (double) lock_wait_timeout) { #ifdef WITH_WSREP - if (!wsrep_on_trx(trx) || + if (!trx->is_wsrep() || (!wsrep_is_BF_lock_timeout(trx) && trx->error_state != DB_DEADLOCK)) { #endif /* WITH_WSREP */ diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 4a4c5112f88..ecbfd03ec93 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1639,7 +1639,7 @@ run_again: if (check_ref) { err = DB_SUCCESS; #ifdef WITH_WSREP - if (!wsrep_on(trx->mysql_thd)) { + if (!trx->is_wsrep()) { goto end_scan; } enum wsrep_key_type key_type; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 7df9629294a..999e8d882ec 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1125,7 +1125,7 @@ row_update_statistics_if_needed( && dict_stats_auto_recalc_is_enabled(table)) { #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && + if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { WSREP_DEBUG("Avoiding background statistics" " calculation for table %s", diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 435eb065d7a..6bb97e917bb 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2019, MariaDB Corporation. +Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1811,7 +1811,7 @@ row_upd_store_row( inline bool wsrep_must_process_fk(const upd_node_t* node, const trx_t* trx) { - if (!wsrep_on_trx(trx)) { + if (!trx->is_wsrep()) { return false; } return que_node_get_type(node->common.parent) != QUE_NODE_UPDATE diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc index 8a1ece92ba4..bf57c308acf 100644 --- a/storage/innobase/srv/srv0conc.cc +++ b/storage/innobase/srv/srv0conc.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2012, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2017, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -213,8 +213,7 @@ srv_conc_enter_innodb_with_atomics( for (;;) { ulint sleep_in_us; #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_trx_is_aborting(trx->mysql_thd)) { + if (trx->is_wsrep() && wsrep_trx_is_aborting(trx->mysql_thd)) { if (wsrep_debug) fprintf(stderr, "srv_conc_enter due to MUST_ABORT"); @@ -421,8 +420,7 @@ retry: return; } #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) { + if (trx->is_wsrep() && wsrep_thd_is_brute_force(trx->mysql_thd)) { srv_conc_force_enter_innodb(trx); return; } @@ -504,8 +502,7 @@ retry: srv_conc.n_waiting++; #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_trx_is_aborting(trx->mysql_thd)) { + if (trx->is_wsrep() && wsrep_trx_is_aborting(trx->mysql_thd)) { os_fast_mutex_unlock(&srv_conc_mutex); if (wsrep_debug) fprintf(stderr, "srv_conc_enter due to MUST_ABORT"); diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 76d501aad53..53c5d1ca82d 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2019, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1331,11 +1331,7 @@ trx_commit_in_memory( ut_ad(!trx->in_ro_trx_list); ut_ad(!trx->in_rw_trx_list); -#ifdef WITH_WSREP - if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } -#endif + trx->lock.was_chosen_as_deadlock_victim = FALSE; trx->dict_operation = TRX_DICT_OP_NONE; trx->error_state = DB_SUCCESS; diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 2aafb1a44ee..2ec16280eb6 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -5,7 +5,7 @@ Copyright (c) 2013, 2018, MariaDB Corporation. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1934,8 +1934,7 @@ innobase_srv_conc_enter_innodb( trx_t* trx) /*!< in: transaction handle */ { #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; + if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; #endif /* WITH_WSREP */ if (srv_thread_concurrency) { if (trx->n_tickets_to_enter_innodb > 0) { @@ -1973,8 +1972,7 @@ innobase_srv_conc_exit_innodb( ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch)); #endif /* UNIV_SYNC_DEBUG */ #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; + if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; #endif /* WITH_WSREP */ /* This is to avoid making an unnecessary function call. */ @@ -2950,6 +2948,9 @@ innobase_trx_init( trx->check_unique_secondary = !thd_test_options( thd, OPTION_RELAXED_UNIQUE_CHECKS); +#ifdef WITH_WSREP + trx->wsrep = wsrep_on(thd); +#endif /* Transaction on start caches the fake_changes state and uses it for complete transaction lifetime. @@ -4676,19 +4677,17 @@ innobase_commit_low( trx_t* trx) /*!< in: transaction handle */ { #ifdef WITH_WSREP - THD* thd = (THD*)trx->mysql_thd; const char* tmp = 0; - if (thd && wsrep_on(thd)) { + if (trx->is_wsrep()) { #ifdef WSREP_PROC_INFO char info[64]; info[sizeof(info) - 1] = '\0'; snprintf(info, sizeof(info) - 1, "innobase_commit_low():trx_commit_for_mysql(%lld)", - (long long) wsrep_thd_trx_seqno(thd)); - tmp = thd_proc_info(thd, info); - + (long long) wsrep_thd_trx_seqno(trx->mysql_thd)); + tmp = thd_proc_info(trx->mysql_thd, info); #else - tmp = thd_proc_info(thd, "innobase_commit_low()"); + tmp = thd_proc_info(trx->mysql_thd, "innobase_commit_low()"); #endif /* WSREP_PROC_INFO */ } #endif /* WITH_WSREP */ @@ -4697,7 +4696,7 @@ innobase_commit_low( trx_commit_for_mysql(trx); } #ifdef WITH_WSREP - if (thd && wsrep_on(thd)) { thd_proc_info(thd, tmp); } + if (trx->is_wsrep()) { thd_proc_info(trx->mysql_thd, tmp); } #endif /* WITH_WSREP */ } @@ -8713,19 +8712,19 @@ ha_innobase::write_row( sql_command = thd_sql_command(user_thd); - if ((sql_command == SQLCOM_ALTER_TABLE - || sql_command == SQLCOM_OPTIMIZE - || sql_command == SQLCOM_CREATE_INDEX + if (num_write_row >= 10000 + && (sql_command == SQLCOM_ALTER_TABLE + || sql_command == SQLCOM_OPTIMIZE + || sql_command == SQLCOM_CREATE_INDEX #ifdef WITH_WSREP - || (wsrep_on(user_thd) && wsrep_load_data_splitting && - sql_command == SQLCOM_LOAD && - !thd_test_options( - user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + || (sql_command == SQLCOM_LOAD && + trx->is_wsrep() && wsrep_load_data_splitting && + !thd_test_options( + user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) #endif /* WITH_WSREP */ - || sql_command == SQLCOM_DROP_INDEX) - && num_write_row >= 10000) { + || sql_command == SQLCOM_DROP_INDEX)) { #ifdef WITH_WSREP - if (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) { + if (sql_command == SQLCOM_LOAD && trx->is_wsrep()) { WSREP_DEBUG("forced trx split for LOAD: %s", wsrep_thd_query(user_thd)); } @@ -8764,9 +8763,8 @@ no_commit: ; } else if (src_table == prebuilt->table) { #ifdef WITH_WSREP - if (wsrep_on(user_thd) && - wsrep_load_data_splitting && - sql_command == SQLCOM_LOAD && + if (sql_command == SQLCOM_LOAD && trx->is_wsrep() && + wsrep_load_data_splitting && !thd_test_options(user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { @@ -8796,9 +8794,8 @@ no_commit: prebuilt->sql_stat_start = TRUE; } else { #ifdef WITH_WSREP - if (wsrep_on(user_thd) && - wsrep_load_data_splitting && - sql_command == SQLCOM_LOAD && + if (sql_command == SQLCOM_LOAD && trx->is_wsrep() && + wsrep_load_data_splitting && !thd_test_options(user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { @@ -8943,21 +8940,19 @@ no_commit: prebuilt->autoinc_offset, prebuilt->autoinc_increment); - if (wsrep_on(current_thd) && + if (trx->is_wsrep() && auto_inc_inserted && wsrep_drupal_282555_workaround && - wsrep_thd_retry_counter(current_thd) == 0 && - !thd_test_options(current_thd, + wsrep_thd_retry_counter(user_thd) == 0 && + !thd_test_options(user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { WSREP_DEBUG( "retrying insert: %s", - (*wsrep_thd_query(current_thd)) ? - wsrep_thd_query(current_thd) : - (char *)"void"); + wsrep_thd_query(user_thd)); error= DB_SUCCESS; wsrep_thd_set_conflict_state( - current_thd, MUST_ABORT); + user_thd, MUST_ABORT); innobase_srv_conc_exit_innodb(prebuilt->trx); /* jump straight to func exit over * later wsrep hooks */ @@ -8995,7 +8990,7 @@ set_max_autoinc: prebuilt autoinc values don't get properly assigned. Fetch values from server side. */ - if (wsrep_on(user_thd) && + if (trx->is_wsrep() && wsrep_thd_exec_mode(user_thd) == REPL_RECV) { wsrep_thd_auto_increment_variables( @@ -9044,18 +9039,16 @@ report_error: user_thd); #ifdef WITH_WSREP - if (!error_result - && wsrep_on(user_thd) - && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE + if (!error_result && trx->is_wsrep() + && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && !wsrep_consistency_check(user_thd) && !wsrep_thd_ignore_table(user_thd)) { if (wsrep_append_keys(user_thd, WSREP_KEY_EXCLUSIVE, record, NULL)) { DBUG_PRINT("wsrep", ("row key failed")); error_result = HA_ERR_INTERNAL_ERROR; - goto wsrep_error; + goto func_exit; } } -wsrep_error: #endif /* WITH_WSREP */ if (error_result == HA_FTS_INVALID_DOCID) { @@ -9536,7 +9529,7 @@ ha_innobase::update_row( prebuilt autoinc values don't get properly assigned. Fetch values from server side. */ - if (wsrep_on(user_thd) && + if (trx->is_wsrep() && wsrep_thd_exec_mode(user_thd) == REPL_RECV) { wsrep_thd_auto_increment_variables( @@ -9581,9 +9574,8 @@ func_exit: innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS && + if (error == DB_SUCCESS && trx->is_wsrep() && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && - wsrep_on(user_thd) && !wsrep_thd_ignore_table(user_thd)) { DBUG_PRINT("wsrep", ("update row key")); @@ -9592,11 +9584,9 @@ func_exit: new_row)) { WSREP_DEBUG("WSREP: UPDATE_ROW_KEY FAILED"); DBUG_PRINT("wsrep", ("row key failed")); - err = HA_ERR_INTERNAL_ERROR; - goto wsrep_error; + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } } -wsrep_error: #endif /* WITH_WSREP */ DBUG_RETURN(err); @@ -9643,25 +9633,20 @@ ha_innobase::delete_row( /* Tell the InnoDB server that there might be work for utility threads: */ - innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS && + if (error == DB_SUCCESS && trx->is_wsrep() && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && - wsrep_on(user_thd) && !wsrep_thd_ignore_table(user_thd)) { if (wsrep_append_keys(user_thd, WSREP_KEY_EXCLUSIVE, record, - NULL)) { + NULL)) { DBUG_PRINT("wsrep", ("delete fail")); - error = (dberr_t) HA_ERR_INTERNAL_ERROR; - goto wsrep_error; + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } } -wsrep_error: #endif /* WITH_WSREP */ - DBUG_RETURN(convert_error_code_to_mysql( error, prebuilt->table->flags, user_thd)); } @@ -10917,8 +10902,7 @@ wsrep_append_foreign_key( int cache_key_len; bool const copy = true; - if (!wsrep_on(trx->mysql_thd) || - wsrep_thd_exec_mode(thd) != LOCAL_STATE) + if (!trx->is_wsrep() || wsrep_thd_exec_mode(thd) != LOCAL_STATE) return DB_SUCCESS; if (!thd || !foreign || @@ -15541,12 +15525,11 @@ ha_innobase::external_lock( THD* thd, /*!< in: handle to the user thread */ int lock_type) /*!< in: lock type */ { - trx_t* trx; - DBUG_ENTER("ha_innobase::external_lock"); DBUG_PRINT("enter",("lock_type: %d", lock_type)); update_thd(thd); + trx_t* trx = prebuilt->trx; /* Statement based binlogging does not work in isolation level READ UNCOMMITTED and READ COMMITTED since the necessary @@ -15560,22 +15543,19 @@ ha_innobase::external_lock( && thd_binlog_format(thd) == BINLOG_FORMAT_STMT && thd_binlog_filter_ok(thd) && thd_sqlcom_can_generate_row_events(thd)) { - bool skip = 0; + bool skip = false; +#ifdef WITH_WSREP + skip = trx->is_wsrep() + && wsrep_thd_exec_mode(thd) != LOCAL_STATE; +#endif /* WITH_WSREP */ /* used by test case */ DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = true;); if (!skip) { -#ifdef WITH_WSREP - if (!wsrep_on(thd) || wsrep_thd_exec_mode(thd) == LOCAL_STATE) - { -#endif /* WITH_WSREP */ - my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), - " InnoDB is limited to row-logging when " - "transaction isolation level is " - "READ COMMITTED or READ UNCOMMITTED."); - DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE); -#ifdef WITH_WSREP - } -#endif /* WITH_WSREP */ + my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), + " InnoDB is limited to row-logging when " + "transaction isolation level is " + "READ COMMITTED or READ UNCOMMITTED."); + DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE); } } @@ -15606,8 +15586,6 @@ ha_innobase::external_lock( } - trx = prebuilt->trx; - prebuilt->sql_stat_start = TRUE; prebuilt->hint_need_to_fetch_extra_cols = 0; diff --git a/storage/xtradb/include/lock0lock.h b/storage/xtradb/include/lock0lock.h index 878a42ea81b..a6b6e08b68b 100644 --- a/storage/xtradb/include/lock0lock.h +++ b/storage/xtradb/include/lock0lock.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1013,8 +1014,6 @@ std::string lock_get_info( const lock_t*); -#define wsrep_on_trx(trx) ((trx)->mysql_thd && wsrep_on((trx)->mysql_thd)) - #ifndef UNIV_NONINL #include "lock0lock.ic" #endif diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h index 448b2429126..5fed8d68e50 100644 --- a/storage/xtradb/include/trx0trx.h +++ b/storage/xtradb/include/trx0trx.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2019, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -818,15 +818,21 @@ struct trx_t{ ro_trx_list the first time they try to acquire a lock ie. by default we treat all read-only transactions as non-locking. */ trx_state_t state; - trx_lock_t lock; /*!< Information about the transaction locks and state. Protected by trx->mutex or lock_sys->mutex or both */ - ulint is_recovered; /*!< 0=normal transaction, - 1=recovered, must be rolled back, + bool is_recovered; /*!< false=normal transaction, + true=recovered, must be rolled back, protected by trx_sys->mutex when trx->in_rw_trx_list holds */ +#ifdef WITH_WSREP + /** whether wsrep_on(mysql_thd) held at the start of transaction */ + bool wsrep; + bool is_wsrep() const { return UNIV_UNLIKELY(wsrep); } +#else /* WITH_WSREP */ + bool is_wsrep() const { return false; } +#endif /* WITH_WSREP */ /* These fields are not protected by any mutex. */ const char* op_info; /*!< English text describing the diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc index c110c83cbe7..4d40111ac20 100644 --- a/storage/xtradb/lock/lock0lock.cc +++ b/storage/xtradb/lock/lock0lock.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2019, MariaDB Corporation. +Copyright (c) 2014, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1770,7 +1770,7 @@ wsrep_kill_victim( ut_ad(trx_mutex_own(lock->trx)); /* quit for native mysql */ - if (!wsrep_on(trx->mysql_thd)) return; + if (!trx->is_wsrep()) return; my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE); my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE); @@ -1856,7 +1856,7 @@ lock_rec_other_has_conflicting( #ifdef WITH_WSREP if (lock_rec_has_to_wait(TRUE, trx, mode, lock, is_supremum)) { - if (wsrep_on_trx(trx)) { + if (trx->is_wsrep()) { trx_mutex_enter(lock->trx); /* Below function will roll back either trx or lock->trx depending on priority of the @@ -2318,8 +2318,7 @@ lock_rec_create( ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted); #ifdef WITH_WSREP - if (c_lock && - wsrep_on_trx(trx) && + if (c_lock && trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { lock_t *hash = (lock_t *)c_lock->hash; lock_t *prev = NULL; @@ -5009,7 +5008,7 @@ lock_table_create( UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock); #ifdef WITH_WSREP - if (c_lock && wsrep_on_trx(trx)) { + if (c_lock && trx->is_wsrep()) { if (wsrep_thd_is_wsrep(trx->mysql_thd) && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { UT_LIST_INSERT_AFTER( @@ -5248,7 +5247,7 @@ lock_table_enqueue_waiting( /* Enqueue the lock request that will wait to be granted */ #ifdef WITH_WSREP - if (trx->lock.was_chosen_as_deadlock_victim && wsrep_on_trx(trx)) { + if (trx->lock.was_chosen_as_deadlock_victim && trx->is_wsrep()) { return(DB_DEADLOCK); } diff --git a/storage/xtradb/lock/lock0wait.cc b/storage/xtradb/lock/lock0wait.cc index fe43ef3cc73..70ade1191d7 100644 --- a/storage/xtradb/lock/lock0wait.cc +++ b/storage/xtradb/lock/lock0wait.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2019, MariaDB Corporation. +Copyright (c) 2014, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -255,8 +255,7 @@ wsrep_is_BF_lock_timeout( const trx_t* trx, bool locked = true) { - if (wsrep_on_trx(trx) - && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { fprintf(stderr, "WSREP: BF lock wait long for trx " TRX_ID_FMT "\n", trx->id); srv_print_innodb_monitor = TRUE; srv_print_innodb_lock_monitor = TRUE; @@ -447,7 +446,7 @@ lock_wait_suspend_thread( if (lock_wait_timeout < 100000000 && wait_time > (double) lock_wait_timeout) { #ifdef WITH_WSREP - if (!wsrep_on_trx(trx) || + if (!trx->is_wsrep() || (!wsrep_is_BF_lock_timeout(trx) && trx->error_state != DB_DEADLOCK)) { #endif /* WITH_WSREP */ diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc index 50da7fb40ad..f7371d6b83e 100644 --- a/storage/xtradb/row/row0ins.cc +++ b/storage/xtradb/row/row0ins.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1651,7 +1651,7 @@ run_again: if (check_ref) { err = DB_SUCCESS; #ifdef WITH_WSREP - if (!wsrep_on(trx->mysql_thd)) { + if (!trx->is_wsrep()) { goto end_scan; } enum wsrep_key_type key_type; diff --git a/storage/xtradb/row/row0upd.cc b/storage/xtradb/row/row0upd.cc index 6324c1d71a1..a5e5988113d 100644 --- a/storage/xtradb/row/row0upd.cc +++ b/storage/xtradb/row/row0upd.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2019, MariaDB Corporation. +Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1814,7 +1814,7 @@ row_upd_store_row( inline bool wsrep_must_process_fk(const upd_node_t* node, const trx_t* trx) { - if (!wsrep_on_trx(trx)) { + if (!trx->is_wsrep()) { return false; } return que_node_get_type(node->common.parent) != QUE_NODE_UPDATE diff --git a/storage/xtradb/srv/srv0conc.cc b/storage/xtradb/srv/srv0conc.cc index 3433d968eb2..d2ededc3894 100644 --- a/storage/xtradb/srv/srv0conc.cc +++ b/storage/xtradb/srv/srv0conc.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2012, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2017, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -218,8 +218,7 @@ srv_conc_enter_innodb_with_atomics( for (;;) { ulint sleep_in_us; #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_trx_is_aborting(trx->mysql_thd)) { + if (trx->is_wsrep() && wsrep_trx_is_aborting(trx->mysql_thd)) { if (wsrep_debug) fprintf(stderr, "srv_conc_enter due to MUST_ABORT"); @@ -430,8 +429,7 @@ retry: return; } #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) { + if (trx->is_wsrep() && wsrep_thd_is_brute_force(trx->mysql_thd)) { srv_conc_force_enter_innodb(trx); return; } @@ -514,8 +512,7 @@ retry: srv_conc.n_waiting++; #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_trx_is_aborting(trx->mysql_thd)) { + if (trx->is_wsrep() && wsrep_trx_is_aborting(trx->mysql_thd)) { os_fast_mutex_unlock(&srv_conc_mutex); if (wsrep_debug) fprintf(stderr, "srv_conc_enter due to MUST_ABORT"); diff --git a/storage/xtradb/trx/trx0roll.cc b/storage/xtradb/trx/trx0roll.cc index 97f08d1fa0c..7624d92a831 100644 --- a/storage/xtradb/trx/trx0roll.cc +++ b/storage/xtradb/trx/trx0roll.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2019, MariaDB Corporation. +Copyright (c) 2016, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -379,8 +379,7 @@ trx_rollback_to_savepoint_for_mysql_low( trx->op_info = ""; #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - trx->lock.was_chosen_as_deadlock_victim) { + if (trx->is_wsrep()) { trx->lock.was_chosen_as_deadlock_victim = FALSE; } #endif @@ -1083,12 +1082,6 @@ trx_roll_try_truncate( if (trx->update_undo) { trx_undo_truncate_end(trx, trx->update_undo, limit); } - -#ifdef WITH_WSREP_OUT - if (wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } -#endif /* WITH_WSREP */ } /***********************************************************************//** diff --git a/storage/xtradb/trx/trx0trx.cc b/storage/xtradb/trx/trx0trx.cc index a65132cf572..bfbd15d62a2 100644 --- a/storage/xtradb/trx/trx0trx.cc +++ b/storage/xtradb/trx/trx0trx.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2019, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1555,11 +1555,7 @@ trx_commit_in_memory( ut_ad(!trx->in_ro_trx_list); ut_ad(!trx->in_rw_trx_list); -#ifdef WITH_WSREP - if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } -#endif + trx->lock.was_chosen_as_deadlock_victim = FALSE; trx->dict_operation = TRX_DICT_OP_NONE; trx->error_state = DB_SUCCESS; From d956175d0d15e8c84e4e3ff5b0798143ce3ccfe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 27 Apr 2020 11:39:46 +0300 Subject: [PATCH 20/35] XtraDB 5.6.47-87.0 The only change is a change of the version number. As noted in commit 02af6278fb7c7889a02d617eb23e82fe7967abd7 there were no changes to InnoDB between MySQL 5.6.46 and 5.6.47 either. --- mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff | 2 +- mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff | 2 +- storage/xtradb/include/univ.i | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff index fe6ec0e6f33..47289d2887b 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff @@ -1215,7 +1215,7 @@ VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL -GLOBAL_VALUE 5.6.47 -+GLOBAL_VALUE 5.6.46-86.2 ++GLOBAL_VALUE 5.6.47-87.0 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff index 5fab6de421a..4e630e5e56f 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff @@ -685,7 +685,7 @@ VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL -GLOBAL_VALUE 5.6.47 -+GLOBAL_VALUE 5.6.46-86.2 ++GLOBAL_VALUE 5.6.47-87.0 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index f5cc649f944..0b7ab3e389e 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -45,10 +45,10 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 6 -#define INNODB_VERSION_BUGFIX 46 +#define INNODB_VERSION_BUGFIX 47 #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 86.2 +#define PERCONA_INNODB_VERSION 87.0 #endif /* Enable UNIV_LOG_ARCHIVE in XtraDB */ From f7437d8a3c45d766eca569a3c71e903fb4891f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 27 Apr 2020 14:29:23 +0300 Subject: [PATCH 21/35] Flag a result dependency on PLUGIN_PERFSCHEMA --- mysql-test/suite/sql_sequence/rebuild.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/sql_sequence/rebuild.test b/mysql-test/suite/sql_sequence/rebuild.test index 7c00e0be7cc..2994b90c98f 100644 --- a/mysql-test/suite/sql_sequence/rebuild.test +++ b/mysql-test/suite/sql_sequence/rebuild.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_perfschema.inc --echo # --echo # MDEV-15977 Assertion `! thd->in_sub_stmt' failed in trans_commit_stmt From 581df0df89c68fc6c5acb59efe89053b2036844a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 27 Apr 2020 15:32:02 +0300 Subject: [PATCH 22/35] MDEV-7962: Follow-up fix for 10.2 dict_stats_update_if_needed(): Replace the parameter THD* with const trx_t& so that trx_t::is_wsrep() can be invoked instead of the more expensive wsrep_on(). Replace also other occurrences of wsrep_on() with trx_t::is_wsrep(). --- storage/innobase/dict/dict0stats_bg.cc | 14 +++++++------- storage/innobase/include/dict0stats.h | 12 ++++++------ storage/innobase/row/row0mysql.cc | 7 +++---- storage/innobase/row/row0purge.cc | 5 ++--- storage/innobase/row/row0uins.cc | 6 +++--- storage/innobase/row/row0umod.cc | 4 ++-- storage/innobase/trx/trx0roll.cc | 11 ++--------- 7 files changed, 25 insertions(+), 34 deletions(-) diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index ec3f0a8eae6..589f53dde38 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -32,6 +32,7 @@ Created Apr 25, 2012 Vasil Dimov #include "srv0start.h" #include "fil0fil.h" #ifdef WITH_WSREP +# include "trx0trx.h" # include "mysql/service_wsrep.h" # include "wsrep.h" # include "log.h" @@ -145,12 +146,12 @@ dict_stats_recalc_pool_add( schedule new estimates for table and index statistics to be calculated. @param[in,out] table persistent or temporary table @param[in] thd current session */ -void dict_stats_update_if_needed(dict_table_t* table, THD* thd) +void dict_stats_update_if_needed(dict_table_t *table, const trx_t &trx) #else /** Update the table modification counter and if necessary, schedule new estimates for table and index statistics to be calculated. @param[in,out] table persistent or temporary table */ -void dict_stats_update_if_needed_func(dict_table_t* table) +void dict_stats_update_if_needed_func(dict_table_t *table) #endif { ut_ad(table->stat_initialized); @@ -177,10 +178,9 @@ void dict_stats_update_if_needed_func(dict_table_t* table) generated row locks and allow BF thread lock waits to be enqueued at head of waiting queue. */ - if (thd - && !wsrep_thd_is_applier(thd) - && wsrep_on(thd) - && wsrep_thd_is_BF(thd, 0)) { + if (trx.is_wsrep() + && !wsrep_thd_is_applier(trx.mysql_thd) + && wsrep_thd_is_BF(trx.mysql_thd, 0)) { WSREP_DEBUG("Avoiding background statistics" " calculation for table %s.", table->name.m_name); diff --git a/storage/innobase/include/dict0stats.h b/storage/innobase/include/dict0stats.h index 98956412ae2..00ac6eb4745 100644 --- a/storage/innobase/include/dict0stats.h +++ b/storage/innobase/include/dict0stats.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2009, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -115,16 +115,16 @@ dict_stats_deinit( /** Update the table modification counter and if necessary, schedule new estimates for table and index statistics to be calculated. @param[in,out] table persistent or temporary table -@param[in] thd current session */ -void dict_stats_update_if_needed(dict_table_t* table, THD* thd) - MY_ATTRIBUTE((nonnull(1))); +@param[in] trx transaction */ +void dict_stats_update_if_needed(dict_table_t *table, const trx_t &trx) + MY_ATTRIBUTE((nonnull)); #else /** Update the table modification counter and if necessary, schedule new estimates for table and index statistics to be calculated. @param[in,out] table persistent or temporary table */ -void dict_stats_update_if_needed_func(dict_table_t* table) +void dict_stats_update_if_needed_func(dict_table_t *table) MY_ATTRIBUTE((nonnull)); -# define dict_stats_update_if_needed(t,thd) dict_stats_update_if_needed_func(t) +# define dict_stats_update_if_needed(t,trx) dict_stats_update_if_needed_func(t) #endif /*********************************************************************//** diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index ac44e32c326..a8139039796 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1526,7 +1526,7 @@ error_exit: memcpy(prebuilt->row_id, node->sys_buf, DATA_ROW_ID_LEN); } - dict_stats_update_if_needed(table, trx->mysql_thd); + dict_stats_update_if_needed(table, *trx); trx->op_info = ""; if (blob_heap != NULL) { @@ -1898,7 +1898,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) } if (update_statistics) { - dict_stats_update_if_needed(prebuilt->table, trx->mysql_thd); + dict_stats_update_if_needed(prebuilt->table, *trx); } else { /* Always update the table modification counter. */ prebuilt->table->stat_modified_counter++; @@ -2151,8 +2151,7 @@ row_update_cascade_for_mysql( } if (stats) { - dict_stats_update_if_needed(node->table, - trx->mysql_thd); + dict_stats_update_if_needed(node->table, *trx); } else { /* Always update the table modification counter. */ diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index b13bf47ce95..34d97e101b8 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1103,8 +1103,7 @@ row_purge_record_func( if (node->table->stat_initialized && srv_stats_include_delete_marked) { dict_stats_update_if_needed( - node->table, - thr->graph->trx->mysql_thd); + node->table, *thr->graph->trx); } MONITOR_INC(MONITOR_N_DEL_ROW_PURGE); } diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index d62e730d800..e648220575b 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -536,8 +536,8 @@ row_undo_ins( already be holding dict_sys->mutex, which would be acquired when updating statistics. */ if (!dict_locked) { - dict_stats_update_if_needed( - node->table, node->trx->mysql_thd); + dict_stats_update_if_needed(node->table, + *node->trx); } } } diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 8e2775a050b..6a7d4dba439 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1301,8 +1301,8 @@ row_undo_mod( already be holding dict_sys->mutex, which would be acquired when updating statistics. */ if (update_statistics && !dict_locked) { - dict_stats_update_if_needed( - node->table, node->trx->mysql_thd); + dict_stats_update_if_needed(node->table, + *node->trx); } else { node->table->stat_modified_counter++; } diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index b6d7aa9f380..20494133e8b 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -409,9 +409,8 @@ trx_rollback_to_savepoint_for_mysql_low( trx->op_info = ""; #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - trx->lock.was_chosen_as_deadlock_victim) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; + if (trx->is_wsrep()) { + trx->lock.was_chosen_as_deadlock_victim = false; } #endif return(err); @@ -932,12 +931,6 @@ trx_roll_try_truncate(trx_t* trx) trx_undo_truncate_end(undo, undo_no, true); mutex_exit(&undo->rseg->mutex); } - -#ifdef WITH_WSREP_OUT - if (wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } -#endif /* WITH_WSREP */ } /***********************************************************************//** From d0150dc14e11f2e0b7ad60b9db40bd65e82e917e Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Mon, 27 Apr 2020 21:46:05 +0300 Subject: [PATCH 23/35] MDEV-20230: mariabackup --ftwrl-wait-timeout never times out on explicit lock --ftwrl-wait-timeout does not finish mariabackup execution when acquired backup lock can't be grabbed for the certain amount of time, it just waits for a long queries finishing before acquiring the lock to avoid unnecessary locking. This commit extends --ftwrl-wait-timeout so, that mariabackup execution is finished if it waits for backup lock during certain amount of time. --- extra/mariabackup/backup_mysql.cc | 124 ++++++++++-------- .../backup_lock_wait_timeout.result | 11 ++ .../mariabackup/backup_lock_wait_timeout.test | 28 ++++ 3 files changed, 108 insertions(+), 55 deletions(-) create mode 100644 mysql-test/suite/mariabackup/backup_lock_wait_timeout.result create mode 100644 mysql-test/suite/mariabackup/backup_lock_wait_timeout.test diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index d5d0c90376e..171c4407ed5 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -959,79 +959,93 @@ Function acquires either a backup tables lock, if supported by the server, or a global read lock (FLUSH TABLES WITH READ LOCK) otherwise. @returns true if lock acquired */ -bool -lock_tables(MYSQL *connection) +bool lock_tables(MYSQL *connection) { - if (have_lock_wait_timeout) { - /* Set the maximum supported session value for - lock_wait_timeout to prevent unnecessary timeouts when the - global value is changed from the default */ - xb_mysql_query(connection, - "SET SESSION lock_wait_timeout=31536000", false); - } + if (have_lock_wait_timeout || opt_lock_wait_timeout) + { + char buf[FN_REFLEN]; + /* Set the maximum supported session value for + lock_wait_timeout if opt_lock_wait_timeout is not set to prevent + unnecessary timeouts when the global value is changed from the default */ + snprintf(buf, sizeof(buf), "SET SESSION lock_wait_timeout=%u", + opt_lock_wait_timeout ? opt_lock_wait_timeout : 31536000); + xb_mysql_query(connection, buf, false); + } - if (have_backup_locks) { - msg("Executing LOCK TABLES FOR BACKUP..."); - xb_mysql_query(connection, "LOCK TABLES FOR BACKUP", false); - return(true); - } + if (have_backup_locks) + { + msg("Executing LOCK TABLES FOR BACKUP..."); + xb_mysql_query(connection, "LOCK TABLES FOR BACKUP", false); + return (true); + } - if (opt_lock_ddl_per_table) { - start_mdl_waiters_killer(); - } + if (opt_lock_ddl_per_table) + { + start_mdl_waiters_killer(); + } - if (!opt_lock_wait_timeout && !opt_kill_long_queries_timeout) { + if (!opt_lock_wait_timeout && !opt_kill_long_queries_timeout) + { - /* We do first a FLUSH TABLES. If a long update is running, the - FLUSH TABLES will wait but will not stall the whole mysqld, and - when the long update is done the FLUSH TABLES WITH READ LOCK - will start and succeed quickly. So, FLUSH TABLES is to lower - the probability of a stage where both mysqldump and most client - connections are stalled. Of course, if a second long update - starts between the two FLUSHes, we have that bad stall. + /* We do first a FLUSH TABLES. If a long update is running, the + FLUSH TABLES will wait but will not stall the whole mysqld, and + when the long update is done the FLUSH TABLES WITH READ LOCK + will start and succeed quickly. So, FLUSH TABLES is to lower + the probability of a stage where both mysqldump and most client + connections are stalled. Of course, if a second long update + starts between the two FLUSHes, we have that bad stall. - Option lock_wait_timeout serve the same purpose and is not - compatible with this trick. - */ + Option lock_wait_timeout serve the same purpose and is not + compatible with this trick. + */ - msg("Executing FLUSH NO_WRITE_TO_BINLOG TABLES..."); + msg("Executing FLUSH NO_WRITE_TO_BINLOG TABLES..."); - xb_mysql_query(connection, - "FLUSH NO_WRITE_TO_BINLOG TABLES", false); - } + xb_mysql_query(connection, "FLUSH NO_WRITE_TO_BINLOG TABLES", false); + } - if (opt_lock_wait_timeout) { - if (!wait_for_no_updates(connection, opt_lock_wait_timeout, - opt_lock_wait_threshold)) { - return(false); - } - } + if (opt_lock_wait_timeout) + { + if (!wait_for_no_updates(connection, opt_lock_wait_timeout, + opt_lock_wait_threshold)) + { + return (false); + } + } - msg("Executing FLUSH TABLES WITH READ LOCK..."); + msg("Executing FLUSH TABLES WITH READ LOCK..."); - if (opt_kill_long_queries_timeout) { - start_query_killer(); - } + if (opt_kill_long_queries_timeout) + { + start_query_killer(); + } - if (have_galera_enabled) { - xb_mysql_query(connection, - "SET SESSION wsrep_causal_reads=0", false); - } + if (have_galera_enabled) + { + xb_mysql_query(connection, "SET SESSION wsrep_causal_reads=0", false); + } - xb_mysql_query(connection, "FLUSH TABLES WITH READ LOCK", false); + xb_mysql_query(connection, "FLUSH TABLES WITH READ LOCK", false, true); + /* Set the maximum supported session value for + lock_wait_timeout to prevent unnecessary timeouts when the + global value is changed from the default */ + if (opt_lock_wait_timeout) + xb_mysql_query(connection, "SET SESSION lock_wait_timeout=31536000", + false); - if (opt_lock_ddl_per_table) { - stop_mdl_waiters_killer(); - } + if (opt_lock_ddl_per_table) + { + stop_mdl_waiters_killer(); + } - if (opt_kill_long_queries_timeout) { - stop_query_killer(); - } + if (opt_kill_long_queries_timeout) + { + stop_query_killer(); + } - return(true); + return (true); } - /*********************************************************************//** If backup locks are used, execute LOCK BINLOG FOR BACKUP provided that we are not in the --no-lock mode and the lock has not been acquired already. diff --git a/mysql-test/suite/mariabackup/backup_lock_wait_timeout.result b/mysql-test/suite/mariabackup/backup_lock_wait_timeout.result new file mode 100644 index 00000000000..9806bc29b47 --- /dev/null +++ b/mysql-test/suite/mariabackup/backup_lock_wait_timeout.result @@ -0,0 +1,11 @@ +CREATE TABLE t(i INT) ENGINE INNODB; +connect con1,localhost,root,,; +BEGIN; +LOCK TABLES t WRITE; +connection default; +# xtrabackup backup +connection con1; +COMMIT; +connection default; +disconnect con1; +DROP TABLE t; diff --git a/mysql-test/suite/mariabackup/backup_lock_wait_timeout.test b/mysql-test/suite/mariabackup/backup_lock_wait_timeout.test new file mode 100644 index 00000000000..e0f43910ef6 --- /dev/null +++ b/mysql-test/suite/mariabackup/backup_lock_wait_timeout.test @@ -0,0 +1,28 @@ +--source include/have_innodb.inc +--source include/count_sessions.inc + +CREATE TABLE t(i INT) ENGINE INNODB; + +connect (con1,localhost,root,,); +BEGIN; +LOCK TABLES t WRITE; + +--connection default + +echo # xtrabackup backup; +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; + +--disable_result_log +--error 1 +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --ftwrl-wait-timeout=1 --target-dir=$targetdir; +--enable_result_log + +--connection con1 +COMMIT; + +--connection default +--disconnect con1 + +DROP TABLE t; +rmdir $targetdir; +--source include/wait_until_count_sessions.inc From c755974775a7a7f4fc24abeacd2fc9ea7bf0c247 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Sat, 25 Apr 2020 13:49:40 +0530 Subject: [PATCH 24/35] MDEV-19611 INPLACE ALTER does not fail on bad implicit default value - Inplace alter shouldn't set default date column as '0000-00-00' when table is not empty. So mysql_inplace_alter_table() copied alter_ctx.error_if_not_empty to a new field of Alter_inplace_info. In ha_innobase::check_if_supported_inplace_alter() should check the error_if_not_empty flag and return INPLACE_NOT_SUPPORTED if the table is not empty --- .../innodb/r/innodb-alter-timestamp.result | 15 +++++ .../innodb/t/innodb-alter-timestamp.test | 21 ++++++ sql/handler.h | 8 ++- sql/sql_table.cc | 4 +- storage/innobase/handler/handler0alter.cc | 64 +++++++++++++++++++ 5 files changed, 108 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-alter-timestamp.result b/mysql-test/suite/innodb/r/innodb-alter-timestamp.result index 56a1df7ce5d..6934484a488 100644 --- a/mysql-test/suite/innodb/r/innodb-alter-timestamp.result +++ b/mysql-test/suite/innodb/r/innodb-alter-timestamp.result @@ -124,3 +124,18 @@ SELECT DISTINCT (CURRENT_TIMESTAMP()-d4) <= 60 FROM t1; (CURRENT_TIMESTAMP()-d4) <= 60 1 DROP TABLE t1; +CREATE TABLE t1(f1 int) ENGINE=InnoDB; +INSERT INTO t1 SELECT * FROM seq_1_to_4096; +connect purge_control,localhost,root,,; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +DELETE FROM t1; +SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE'; +ALTER TABLE t1 ADD f2 DATE NOT NULL, ALGORITHM=INPLACE; +INSERT INTO t1 VALUES (1, now()); +Warnings: +Note 1265 Data truncated for column 'f2' at row 1 +ALTER TABLE t1 ADD f3 DATE NOT NULL, ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY +DROP TABLE t1; +disconnect purge_control; diff --git a/mysql-test/suite/innodb/t/innodb-alter-timestamp.test b/mysql-test/suite/innodb/t/innodb-alter-timestamp.test index 1fabdc8f24d..28b09b18e10 100644 --- a/mysql-test/suite/innodb/t/innodb-alter-timestamp.test +++ b/mysql-test/suite/innodb/t/innodb-alter-timestamp.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_sequence.inc CREATE TABLE t1 (i1 INT UNSIGNED NULL DEFAULT 42) ENGINE=innodb; INSERT INTO t1 VALUES(NULL); @@ -82,3 +83,23 @@ ALTER TABLE t1 ADD COLUMN d4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP; SELECT COUNT(DISTINCT d4),COUNT(d4),COUNT(*) FROM t1; SELECT DISTINCT (CURRENT_TIMESTAMP()-d4) <= 60 FROM t1; DROP TABLE t1; + +# MDEV-19611 INPLACE ALTER does not fail on bad implicit default value + +# Empty-table +CREATE TABLE t1(f1 int) ENGINE=InnoDB; +INSERT INTO t1 SELECT * FROM seq_1_to_4096; +connect(purge_control,localhost,root,,); +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; +DELETE FROM t1; +SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE'; +ALTER TABLE t1 ADD f2 DATE NOT NULL, ALGORITHM=INPLACE; + +# Non-empty table +INSERT INTO t1 VALUES (1, now()); +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t1 ADD f3 DATE NOT NULL, ALGORITHM=INPLACE; +DROP TABLE t1; +disconnect purge_control; diff --git a/sql/handler.h b/sql/handler.h index 94c652359d2..656b376da8a 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2352,11 +2352,14 @@ public: */ const char *unsupported_reason; + /** true when InnoDB should abort the alter when table is not empty */ + bool error_if_not_empty; + Alter_inplace_info(HA_CREATE_INFO *create_info_arg, Alter_info *alter_info_arg, KEY *key_info_arg, uint key_count_arg, partition_info *modified_part_info_arg, - bool ignore_arg) + bool ignore_arg, bool error_non_empty) : create_info(create_info_arg), alter_info(alter_info_arg), key_info_buffer(key_info_arg), @@ -2371,7 +2374,8 @@ public: modified_part_info(modified_part_info_arg), ignore(ignore_arg), online(false), - unsupported_reason(NULL) + unsupported_reason(NULL), + error_if_not_empty(error_non_empty) {} ~Alter_inplace_info() diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 86a93d4c8c9..ed1c3c401d3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9814,7 +9814,7 @@ do_continue:; Alter_inplace_info ha_alter_info(create_info, alter_info, key_info, key_count, IF_PARTITIONING(thd->work_part_info, NULL), - ignore); + ignore, alter_ctx.error_if_not_empty); TABLE *altered_table= NULL; bool use_inplace= true; @@ -10261,7 +10261,7 @@ err_new_table_cleanup: thd->abort_on_warning= true; make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN, f_val, strlength(f_val), t_type, - new_table->s, + new_table ? new_table->s : table->s, alter_ctx.datetime_field->field_name.str); thd->abort_on_warning= save_abort_on_warning; } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index be6bc669349..0686c21c711 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -866,6 +866,63 @@ innobase_fts_check_doc_id_col( return(false); } +/** Check whether the table is empty. +@param[in] table table to be checked +@return true if table is empty */ +static bool innobase_table_is_empty(const dict_table_t *table) +{ + dict_index_t *clust_index= dict_table_get_first_index(table); + mtr_t mtr; + btr_pcur_t pcur; + buf_block_t *block; + page_cur_t *cur; + const rec_t *rec; + bool next_page= false; + + mtr.start(); + btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF, + &pcur, true, 0, &mtr); + btr_pcur_move_to_next_user_rec(&pcur, &mtr); + if (!rec_is_metadata(btr_pcur_get_rec(&pcur), clust_index)) + btr_pcur_move_to_prev_on_page(&pcur); +scan_leaf: + cur= btr_pcur_get_page_cur(&pcur); + page_cur_move_to_next(cur); +next_page: + if (next_page) + { + uint32_t next_page_no= btr_page_get_next(page_cur_get_page(cur)); + if (next_page_no == FIL_NULL) + { + mtr.commit(); + return true; + } + + next_page= false; + block= page_cur_get_block(cur); + block= btr_block_get(page_id_t(block->page.id.space(), next_page_no), + block->page.size, BTR_SEARCH_LEAF, clust_index, + &mtr); + btr_leaf_page_release(page_cur_get_block(cur), BTR_SEARCH_LEAF, &mtr); + page_cur_set_before_first(block, cur); + page_cur_move_to_next(cur); + } + + rec= page_cur_get_rec(cur); + if (rec_get_deleted_flag(rec, dict_table_is_comp(table))); + else if (!page_rec_is_supremum(rec)) + { + mtr.commit(); + return false; + } + else + { + next_page= true; + goto next_page; + } + goto scan_leaf; +} + /** Check if InnoDB supports a particular alter table in-place @param altered_table TABLE object for new version of table. @param ha_alter_info Structure describing changes to be done @@ -1078,6 +1135,13 @@ ha_innobase::check_if_supported_inplace_alter( DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } + /* '0000-00-00' value isn't allowed for datetime datatype + for newly added column when table is not empty */ + if (ha_alter_info->error_if_not_empty + && !innobase_table_is_empty(m_prebuilt->table)) { + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + bool add_drop_v_cols = false; /* If there is add or drop virtual columns, we will support operations From cf64d27badc5c90ae72c590c9043a0e3ed837fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Apr 2020 11:40:04 +0300 Subject: [PATCH 25/35] Remove a duplicated copyright message --- storage/xtradb/handler/ha_innodb.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 2ec16280eb6..1593bf8ab46 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1,7 +1,6 @@ /***************************************************************************** Copyright (c) 2000, 2019, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. From cce1b6e245a7ee30e6ebfcd45556e8caa6e754c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Apr 2020 11:46:29 +0300 Subject: [PATCH 26/35] MDEV-22392 Race condition on SET GLOBAL innodb_buffer_pool_evict='uncompressed' innodb_buffer_pool_evict_uncompressed(): Restart the loop when prev_block might not enjoy mutex protection. This is based on mysql/mysql-server@eccaecac070b6747ecf14d6b9150791f8c3e8f6d --- storage/innobase/handler/ha_innodb.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index f9bad3a128c..a1505eecd29 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2019, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2020, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. @@ -17850,10 +17850,7 @@ static char* srv_buffer_pool_evict; Evict all uncompressed pages of compressed tables from the buffer pool. Keep the compressed pages in the buffer pool. @return whether all uncompressed pages were evicted */ -static MY_ATTRIBUTE((warn_unused_result)) -bool -innodb_buffer_pool_evict_uncompressed(void) -/*=======================================*/ +static bool innodb_buffer_pool_evict_uncompressed() { bool all_evicted = true; @@ -17874,9 +17871,13 @@ innodb_buffer_pool_evict_uncompressed(void) if (!buf_LRU_free_page(&block->page, false)) { all_evicted = false; + block = prev_block; + } else { + /* Because buf_LRU_free_page() may release + and reacquire buf_pool_t::mutex, prev_block + may be invalid. */ + block = UT_LIST_GET_LAST(buf_pool->unzip_LRU); } - - block = prev_block; } buf_pool_mutex_exit(buf_pool); From 704180747658019aa52173e44e99229b8ae56efa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Apr 2020 14:51:25 +0300 Subject: [PATCH 27/35] MDEV-22393 Corruption for SET GLOBAL innodb_ string variables Several MYSQL_SYSVAR_STR parameters that employ both a validate function callback fail to copy the string for saving the validated value. The affected variables include the following: innodb_ft_aux_table innodb_ft_server_stopword_table innodb_ft_user_stopword_table innodb_buffer_pool_filename The test case is an enhanced version of mysql/mysql-server@0b0c30641fd66336e87394ac28587e40864f8af9 and the code changes are inspired by their fixes. We are also importing and adjusting the test innodb_fts.stopword to get coverage for the variable innodb_ft_user_stopword_table. buf_dump(), buf_load(): Protect srv_buf_dump_filename with LOCK_global_system_variables. fts_load_user_stopword(): Minor cleanup fts_load_stopword(): Remove the parameter global_stopword_table. innobase_fts_load_stopword(): Protect innodb_server_stopword_table against concurrent SET GLOBAL. --- .../innodb/r/innodb_sys_var_valgrind.result | 73 ++ .../innodb/t/innodb_sys_var_valgrind.test | 70 ++ mysql-test/suite/innodb_fts/r/stopword.result | 735 ++++++++++++++++++ mysql-test/suite/innodb_fts/t/stopword.opt | 1 + mysql-test/suite/innodb_fts/t/stopword.test | 657 ++++++++++++++++ storage/innobase/buf/buf0dump.cc | 8 +- storage/innobase/fts/fts0fts.cc | 81 +- storage/innobase/handler/ha_innodb.cc | 121 +-- storage/innobase/include/fts0fts.h | 12 +- storage/xtradb/buf/buf0dump.cc | 8 +- storage/xtradb/fts/fts0fts.cc | 81 +- storage/xtradb/handler/ha_innodb.cc | 121 +-- storage/xtradb/include/fts0fts.h | 12 +- 13 files changed, 1764 insertions(+), 216 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb_sys_var_valgrind.result create mode 100644 mysql-test/suite/innodb/t/innodb_sys_var_valgrind.test create mode 100644 mysql-test/suite/innodb_fts/r/stopword.result create mode 100644 mysql-test/suite/innodb_fts/t/stopword.opt create mode 100644 mysql-test/suite/innodb_fts/t/stopword.test diff --git a/mysql-test/suite/innodb/r/innodb_sys_var_valgrind.result b/mysql-test/suite/innodb/r/innodb_sys_var_valgrind.result new file mode 100644 index 00000000000..32d87b4668a --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_sys_var_valgrind.result @@ -0,0 +1,73 @@ +# +# Bug #29717909 MEMORY LIFETIME OF VARIABLES BETWEEN CHECK AND UPDATE INCORRECTLY MANAGED +# +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +NULL +create table user_stopword_1(value varchar(30)) engine = innodb; +create table user_stopword_2(value varchar(30)) engine = innodb; +set @blah = 'test/user_stopword_1'; +SET GLOBAL innodb_ft_server_stopword_table= @blah; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +test/user_stopword_1 +set @blah = 'test/user_stopword_2'; +SET GLOBAL innodb_ft_server_stopword_table= @blah; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +test/user_stopword_2 +SET GLOBAL innodb_ft_server_stopword_table= NULL; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +NULL +SET GLOBAL innodb_ft_server_stopword_table= default; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +NULL +drop table user_stopword_1, user_stopword_2; +select @@innodb_buffer_pool_filename; +@@innodb_buffer_pool_filename +ib_buffer_pool +set @blah='hello'; +set global innodb_buffer_pool_filename = @blah; +select @@innodb_buffer_pool_filename; +@@innodb_buffer_pool_filename +hello +set global innodb_buffer_pool_filename="bye"; +select @@innodb_buffer_pool_filename; +@@innodb_buffer_pool_filename +bye +set global innodb_buffer_pool_filename=NULL; +ERROR 42000: Variable 'innodb_buffer_pool_filename' can't be set to the value of 'NULL' +select @@innodb_buffer_pool_filename; +@@innodb_buffer_pool_filename +bye +set global innodb_buffer_pool_filename=default; +select @@innodb_buffer_pool_filename; +@@innodb_buffer_pool_filename +ib_buffer_pool +CREATE TABLE t1 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +opening_line TEXT(500), author VARCHAR(200), title VARCHAR(200), FULLTEXT idx +(opening_line)) ENGINE=InnoDB; +CREATE TABLE t2 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +opening_line TEXT(500), author VARCHAR(200), title VARCHAR(200), FULLTEXT idx +(opening_line)) ENGINE=InnoDB; +select @@innodb_ft_aux_table; +@@innodb_ft_aux_table +NULL +set @blah = 'test/t1'; +SET GLOBAL innodb_ft_aux_table = @blah; +select @@innodb_ft_aux_table; +@@innodb_ft_aux_table +test/t1 +set @blah = 'test/t2'; +SET GLOBAL innodb_ft_aux_table = @blah; +SET GLOBAL innodb_ft_aux_table = NULL; +select @@innodb_ft_aux_table; +@@innodb_ft_aux_table +NULL +SET GLOBAL innodb_ft_aux_table =default; +select @@innodb_ft_aux_table; +@@innodb_ft_aux_table +NULL +drop table t1,t2; diff --git a/mysql-test/suite/innodb/t/innodb_sys_var_valgrind.test b/mysql-test/suite/innodb/t/innodb_sys_var_valgrind.test new file mode 100644 index 00000000000..2e1391355b9 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_sys_var_valgrind.test @@ -0,0 +1,70 @@ +--source include/have_innodb.inc + +--echo # +--echo # Bug #29717909 MEMORY LIFETIME OF VARIABLES BETWEEN CHECK AND UPDATE INCORRECTLY MANAGED +--echo # + +#Test innodb_ft_server_stopword_table (global variable) +select @@innodb_ft_server_stopword_table; +create table user_stopword_1(value varchar(30)) engine = innodb; +create table user_stopword_2(value varchar(30)) engine = innodb; + +set @blah = 'test/user_stopword_1'; +SET GLOBAL innodb_ft_server_stopword_table= @blah; +select @@innodb_ft_server_stopword_table; + +set @blah = 'test/user_stopword_2'; +SET GLOBAL innodb_ft_server_stopword_table= @blah; +select @@innodb_ft_server_stopword_table; + +SET GLOBAL innodb_ft_server_stopword_table= NULL; +select @@innodb_ft_server_stopword_table; + +SET GLOBAL innodb_ft_server_stopword_table= default; +select @@innodb_ft_server_stopword_table; + +drop table user_stopword_1, user_stopword_2; + +#Test innodb_buffer_pool_filename (global variable) + +select @@innodb_buffer_pool_filename; + +set @blah='hello'; +set global innodb_buffer_pool_filename = @blah; +select @@innodb_buffer_pool_filename; + +set global innodb_buffer_pool_filename="bye"; +select @@innodb_buffer_pool_filename; + +--error ER_WRONG_VALUE_FOR_VAR +set global innodb_buffer_pool_filename=NULL; +select @@innodb_buffer_pool_filename; + +set global innodb_buffer_pool_filename=default; +select @@innodb_buffer_pool_filename; + +#Test innodb_ft_aux_table (global variable) +CREATE TABLE t1 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +opening_line TEXT(500), author VARCHAR(200), title VARCHAR(200), FULLTEXT idx +(opening_line)) ENGINE=InnoDB; + +CREATE TABLE t2 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +opening_line TEXT(500), author VARCHAR(200), title VARCHAR(200), FULLTEXT idx +(opening_line)) ENGINE=InnoDB; + +select @@innodb_ft_aux_table; + +set @blah = 'test/t1'; +SET GLOBAL innodb_ft_aux_table = @blah; +select @@innodb_ft_aux_table; + +set @blah = 'test/t2'; +SET GLOBAL innodb_ft_aux_table = @blah; + +SET GLOBAL innodb_ft_aux_table = NULL; +select @@innodb_ft_aux_table; + +SET GLOBAL innodb_ft_aux_table =default; +select @@innodb_ft_aux_table; + +drop table t1,t2; diff --git a/mysql-test/suite/innodb_fts/r/stopword.result b/mysql-test/suite/innodb_fts/r/stopword.result new file mode 100644 index 00000000000..51ededd675e --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/stopword.result @@ -0,0 +1,735 @@ +call mtr.add_suppression("\\[ERROR\\] InnoDB: user stopword table not_defined does not exist."); +call mtr.add_suppression("\\[ERROR\\] InnoDB: user stopword table test/user_stopword_session does not exist."); +select * from information_schema.innodb_ft_default_stopword; +value +a +about +an +are +as +at +be +by +com +de +en +for +from +how +i +in +is +it +la +of +on +or +that +the +this +to +was +what +when +where +who +will +with +und +the +www +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles (title,body) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SELECT * FROM articles WHERE MATCH (title,body) +AGAINST ('the' IN NATURAL LANGUAGE MODE); +id title body +SET @innodb_ft_server_stopword_table_orig=@@innodb_ft_server_stopword_table; +SET @innodb_ft_enable_stopword_orig=@@innodb_ft_enable_stopword; +SET @innodb_ft_user_stopword_table_orig=@@innodb_ft_user_stopword_table; +set global innodb_ft_server_stopword_table = "not_defined"; +ERROR 42000: Variable 'innodb_ft_server_stopword_table' can't be set to the value of 'not_defined' +set global innodb_ft_server_stopword_table = NULL; +create table user_stopword(value varchar(30)) engine = innodb; +set global innodb_ft_server_stopword_table = "test/user_stopword"; +drop index title on articles; +create fulltext index idx on articles(title, body); +SELECT * FROM articles WHERE MATCH (title,body) +AGAINST ('the' IN NATURAL LANGUAGE MODE); +id title body +5 MySQL vs. YourSQL In the following database comparison ... +CREATE TABLE articles_2 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles_2 (title, body) +VALUES ('test for stopwords','this is it...'); +SELECT * FROM articles_2 WHERE MATCH (title,body) +AGAINST ('this' IN NATURAL LANGUAGE MODE); +id title body +1 test for stopwords this is it... +insert into user_stopword values("this"); +CREATE TABLE articles_3 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles_3 (title, body) +VALUES ('test for stopwords','this is it...'); +SELECT * FROM articles_3 WHERE MATCH (title,body) +AGAINST ('this' IN NATURAL LANGUAGE MODE); +id title body +create table user_stopword_session(value varchar(30)) engine = innodb; +insert into user_stopword_session values("session"); +set session innodb_ft_user_stopword_table="test/user_stopword_session"; +CREATE TABLE articles_4 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles_4 (title, body) +VALUES ('test for session stopwords','this should also be excluded...'); +SELECT * FROM articles_4 WHERE MATCH (title,body) +AGAINST ('session' IN NATURAL LANGUAGE MODE); +id title body +SELECT * FROM articles_4 WHERE MATCH (title,body) +AGAINST ('this' IN NATURAL LANGUAGE MODE); +id title body +1 test for session stopwords this should also be excluded... +CREATE TABLE articles_5 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles_5 (title, body) +VALUES ('test for session stopwords','this should also be excluded...'); +SELECT * FROM articles_5 WHERE MATCH (title,body) +AGAINST ('session' IN NATURAL LANGUAGE MODE); +id title body +1 test for session stopwords this should also be excluded... +drop table articles; +drop table articles_2; +drop table articles_3; +drop table articles_4; +drop table articles_5; +drop table user_stopword; +drop table user_stopword_session; +SET GLOBAL innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT `idx` (title,body) +) ENGINE=InnoDB; +SHOW CREATE TABLE articles; +Table Create Table +articles CREATE TABLE `articles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(200) DEFAULT NULL, + `body` text, + PRIMARY KEY (`id`), + FULLTEXT KEY `idx` (`title`,`body`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO articles (title,body) VALUES +('MySQL from Tutorial','DBMS stands for DataBase ...') , +('when To Use MySQL Well','After that you went through a ...'), +('where will Optimizing MySQL','In what tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +id title body +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE id = 7; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 7; +id title body +7 update the record to see will is indexed or not +DELETE FROM articles WHERE id = 7; +SET global innodb_ft_server_stopword_table = NULL; +SET SESSION innodb_ft_enable_stopword = 0; +select @@innodb_ft_enable_stopword; +@@innodb_ft_enable_stopword +0 +SET global innodb_ft_user_stopword_table = NULL; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +id title body +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE id = 8; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +SELECT * FROM articles WHERE id = 8; +id title body +8 update the record to see will is indexed or not +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 8; +id title body +8 update the record to see will is indexed or not +DELETE FROM articles WHERE id = 8; +ALTER TABLE articles DROP INDEX idx; +SHOW CREATE TABLE articles; +Table Create Table +articles CREATE TABLE `articles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(200) DEFAULT NULL, + `body` text, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1 +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +ANALYZE TABLE articles; +Table Op Msg_type Msg_text +test.articles analyze status OK +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +2 when To Use MySQL Well After that you went through a ... +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +1 MySQL from Tutorial DBMS stands for DataBase ... +6 MySQL Security When configured properly, MySQL ... +2 when To Use MySQL Well After that you went through a ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +5 MySQL vs. YourSQL In the following database comparison ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +2 when To Use MySQL Well After that you went through a ... +3 where will Optimizing MySQL In what tutorial we will show ... +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +1 MySQL from Tutorial DBMS stands for DataBase ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +9 the record will not index the , will words +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +id title body +9 the record will not index the , will words +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT COUNT(*),max(id) FROM articles; +COUNT(*) max(id) +7 9 +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +9 update the record to see will is indexed or not +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +9 update the record to see will is indexed or not +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 9; +id title body +DROP TABLE articles; +SET SESSION innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=@innodb_ft_server_stopword_table_orig; +SET GLOBAL innodb_ft_user_stopword_table=@innodb_ft_user_stopword_table_orig; +SET SESSION innodb_ft_user_stopword_table=default; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT `idx` (title,body) +) ENGINE=InnoDB; +INSERT INTO articles (title,body) VALUES +('MySQL from Tutorial','DBMS stands for DataBase ...') , +('when To Use MySQL Well','After that you went through a ...'), +('where will Optimizing MySQL','In what tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +create table user_stopword(value varchar(30)) engine = innodb; +set session innodb_ft_user_stopword_table = "test/user_stopword"; +create table server_stopword(value varchar(30)) engine = innodb; +set global innodb_ft_server_stopword_table = "test/server_stopword"; +insert into user_stopword values("this"),("will"),("the"); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +insert into server_stopword values("what"),("where"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +DELETE FROM user_stopword; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +insert into user_stopword values("this"),("will"),("the"); +ALTER TABLE articles DROP INDEX idx; +SET SESSION innodb_ft_enable_stopword = 0; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SET SESSION innodb_ft_enable_stopword = 1; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table = default; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +DROP TABLE articles,user_stopword,server_stopword; +SET innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; +SET SESSION innodb_ft_user_stopword_table=default; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT `idx` (title,body) +) ENGINE=InnoDB; +SHOW CREATE TABLE articles; +Table Create Table +articles CREATE TABLE `articles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(200) DEFAULT NULL, + `body` text, + PRIMARY KEY (`id`), + FULLTEXT KEY `idx` (`title`,`body`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO articles (title,body) VALUES +('MySQL from Tutorial','DBMS stands for DataBase ...') , +('when To Use MySQL Well','After that you went through a ...'), +('where will Optimizing MySQL','In what tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +create table user_stopword(value varchar(30)) engine = innodb; +set session innodb_ft_user_stopword_table = "test/user_stopword"; +insert into user_stopword values("mysqld"),("DBMS"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +id title body +1 MySQL from Tutorial DBMS stands for DataBase ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); +id title body +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); +id title body +set session innodb_ft_user_stopword_table = default; +create table server_stopword(value varchar(30)) engine = innodb; +set global innodb_ft_server_stopword_table = "test/server_stopword"; +insert into server_stopword values("root"),("properly"); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); +id title body +set session innodb_ft_user_stopword_table = "test/user_stopword"; +set global innodb_ft_server_stopword_table = "test/server_stopword"; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +id title body +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); +id title body +6 MySQL Security When configured properly, MySQL ... +set session innodb_ft_user_stopword_table = "test/user_stopword"; +DELETE FROM user_stopword; +set global innodb_ft_server_stopword_table = "test/server_stopword"; +DELETE FROM server_stopword; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +id title body +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); +id title body +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +id title body +1 MySQL from Tutorial DBMS stands for DataBase ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); +id title body +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +DROP TABLE articles,user_stopword,server_stopword; +SET SESSION innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; +SET SESSION innodb_ft_user_stopword_table=default; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT `idx` (title,body) +) ENGINE=InnoDB; +SHOW CREATE TABLE articles; +Table Create Table +articles CREATE TABLE `articles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(200) DEFAULT NULL, + `body` text, + PRIMARY KEY (`id`), + FULLTEXT KEY `idx` (`title`,`body`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO articles (title,body) VALUES +('MySQL from Tutorial','DBMS stands for DataBase ...') , +('when To Use MySQL Well','After that you went through a ...'), +('where will Optimizing MySQL','In what tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SET SESSION innodb_ft_enable_stopword = 0; +select @@innodb_ft_enable_stopword; +@@innodb_ft_enable_stopword +0 +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +"In connection 1" +select @@innodb_ft_enable_stopword; +@@innodb_ft_enable_stopword +1 +ANALYZE TABLE articles; +Table Op Msg_type Msg_text +test.articles analyze status OK +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +2 when To Use MySQL Well After that you went through a ... +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +1 MySQL from Tutorial DBMS stands for DataBase ... +6 MySQL Security When configured properly, MySQL ... +2 when To Use MySQL Well After that you went through a ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +5 MySQL vs. YourSQL In the following database comparison ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +2 when To Use MySQL Well After that you went through a ... +3 where will Optimizing MySQL In what tutorial we will show ... +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +1 MySQL from Tutorial DBMS stands for DataBase ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SET SESSION innodb_ft_enable_stopword = 1; +select @@innodb_ft_enable_stopword; +@@innodb_ft_enable_stopword +1 +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +"In connection default" +select @@innodb_ft_enable_stopword; +@@innodb_ft_enable_stopword +0 +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +id title body +SET SESSION innodb_ft_enable_stopword = 1; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +id title body +"In connection 1" +SET SESSION innodb_ft_enable_stopword = 1; +create table user_stopword(value varchar(30)) engine = innodb; +set session innodb_ft_user_stopword_table = "test/user_stopword"; +insert into user_stopword values("this"),("will"),("the"); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +"In connection default" +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +select @@innodb_ft_user_stopword_table; +@@innodb_ft_user_stopword_table +NULL +create table user_stopword_1(value varchar(30)) engine = innodb; +set session innodb_ft_user_stopword_table = "test/user_stopword_1"; +insert into user_stopword_1 values("when"); +SET SESSION innodb_ft_enable_stopword = 1; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +id title body +2 when To Use MySQL Well After that you went through a ... +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('when'); +id title body +2 when To Use MySQL Well After that you went through a ... +6 MySQL Security When configured properly, MySQL ... +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('when'); +id title body +"In connection 1" +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table=default; +select @@innodb_ft_user_stopword_table; +@@innodb_ft_user_stopword_table +NULL +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +NULL +create table server_stopword(value varchar(30)) engine = innodb; +SET GLOBAL innodb_ft_server_stopword_table = "test/server_stopword"; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +test/server_stopword +insert into server_stopword values("when"),("the"); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('the'); +id title body +"In connection default" +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table=default; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +test/server_stopword +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +insert into server_stopword values("where"),("will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('the'); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); +id title body +DROP TABLE articles,user_stopword,user_stopword_1,server_stopword; +SET GLOBAL innodb_ft_user_stopword_table=@innodb_ft_user_stopword_table_orig; +SET GLOBAL innodb_ft_server_stopword_table=@innodb_ft_server_stopword_table_orig; diff --git a/mysql-test/suite/innodb_fts/t/stopword.opt b/mysql-test/suite/innodb_fts/t/stopword.opt new file mode 100644 index 00000000000..d6938c3b1ea --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/stopword.opt @@ -0,0 +1 @@ +--innodb-ft-default-stopword diff --git a/mysql-test/suite/innodb_fts/t/stopword.test b/mysql-test/suite/innodb_fts/t/stopword.test new file mode 100644 index 00000000000..5105a6d2fec --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/stopword.test @@ -0,0 +1,657 @@ +# This is the basic function tests for innodb FTS + +-- source include/have_innodb.inc + +call mtr.add_suppression("\\[ERROR\\] InnoDB: user stopword table not_defined does not exist."); +call mtr.add_suppression("\\[ERROR\\] InnoDB: user stopword table test/user_stopword_session does not exist."); + +select * from information_schema.innodb_ft_default_stopword; + +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL Tutorial','DBMS stands for DataBase ...') , + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# "the" is in the default stopword, it would not be selected +SELECT * FROM articles WHERE MATCH (title,body) + AGAINST ('the' IN NATURAL LANGUAGE MODE); + +SET @innodb_ft_server_stopword_table_orig=@@innodb_ft_server_stopword_table; +SET @innodb_ft_enable_stopword_orig=@@innodb_ft_enable_stopword; +SET @innodb_ft_user_stopword_table_orig=@@innodb_ft_user_stopword_table; + +# Provide user defined stopword table, if not (correctly) defined, +# it will be rejected +--error ER_WRONG_VALUE_FOR_VAR +set global innodb_ft_server_stopword_table = "not_defined"; +set global innodb_ft_server_stopword_table = NULL; + +# Define a correct formated user stopword table +create table user_stopword(value varchar(30)) engine = innodb; + +# The set operation should be successful +set global innodb_ft_server_stopword_table = "test/user_stopword"; + +drop index title on articles; + +create fulltext index idx on articles(title, body); + +# Now we should be able to find "the" +SELECT * FROM articles WHERE MATCH (title,body) + AGAINST ('the' IN NATURAL LANGUAGE MODE); + +# Nothing inserted into the default stopword, so essentially +# nothing get screened. The new stopword could only be +# effective for table created thereafter +CREATE TABLE articles_2 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +INSERT INTO articles_2 (title, body) + VALUES ('test for stopwords','this is it...'); + +# Now we can find record with "this" +SELECT * FROM articles_2 WHERE MATCH (title,body) + AGAINST ('this' IN NATURAL LANGUAGE MODE); + +# Ok, let's instantiate some value into user supplied stop word +# table +insert into user_stopword values("this"); + +# Ok, let's repeat with the new table again. +CREATE TABLE articles_3 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +INSERT INTO articles_3 (title, body) + VALUES ('test for stopwords','this is it...'); + +# Now we should NOT find record with "this" +SELECT * FROM articles_3 WHERE MATCH (title,body) + AGAINST ('this' IN NATURAL LANGUAGE MODE); + +# Test session level stopword control "innodb_user_stopword_table" +create table user_stopword_session(value varchar(30)) engine = innodb; + +insert into user_stopword_session values("session"); + +set session innodb_ft_user_stopword_table="test/user_stopword_session"; + +CREATE TABLE articles_4 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +INSERT INTO articles_4 (title, body) + VALUES ('test for session stopwords','this should also be excluded...'); + +# "session" is excluded +SELECT * FROM articles_4 WHERE MATCH (title,body) + AGAINST ('session' IN NATURAL LANGUAGE MODE); + +# But we can find record with "this" +SELECT * FROM articles_4 WHERE MATCH (title,body) + AGAINST ('this' IN NATURAL LANGUAGE MODE); + +--connect (con1,localhost,root,,) +CREATE TABLE articles_5 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +INSERT INTO articles_5 (title, body) + VALUES ('test for session stopwords','this should also be excluded...'); + +# "session" should be found since the stopword table is session specific +SELECT * FROM articles_5 WHERE MATCH (title,body) + AGAINST ('session' IN NATURAL LANGUAGE MODE); + +--connection default +drop table articles; +drop table articles_2; +drop table articles_3; +drop table articles_4; +drop table articles_5; +drop table user_stopword; +drop table user_stopword_session; + +SET GLOBAL innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; + +#--------------------------------------------------------------------------------------- +# Behavior : +# The stopword is loaded into memory at +# 1) create fulltext index time, +# 2) boot server, +# 3) first time FTs is used +# So if you already created a FTS index, and then turn off stopword +# or change stopword table content it won't affect the FTS +# that already created since the stopword list are already loaded. +# It will only affect the new FTS index created after you changed +# the settings. + +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT `idx` (title,body) + ) ENGINE=InnoDB; + +SHOW CREATE TABLE articles; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL from Tutorial','DBMS stands for DataBase ...') , + ('when To Use MySQL Well','After that you went through a ...'), + ('where will Optimizing MySQL','In what tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# Case : server_stopword=default +# Try to Search default stopword from innodb, "where", "will", "what" +# and "when" are all stopwords +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +# boolean No result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +# no result expected +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +# no result expected +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +# Not going to update as where condition can not find record +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +# Update the record +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE id = 7; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +# Delete will not work as where condition do not return +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 7; +DELETE FROM articles WHERE id = 7; + + + +# Case : Turn OFF stopword list variable and search stopword on OLD index. +# disable stopword list +SET global innodb_ft_server_stopword_table = NULL; +SET SESSION innodb_ft_enable_stopword = 0; +select @@innodb_ft_enable_stopword; +SET global innodb_ft_user_stopword_table = NULL; + +# search default stopword with innodb_ft_enable_stopword is OFF. +# No records expected even though we turned OFF stopwod filtering +# (refer Behavior (at the top of the test) for explanation ) +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +# Not going to update as where condition can not find record +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +# Update the record +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE id = 8; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +SELECT * FROM articles WHERE id = 8; +# Delete will not work as where condition do not return +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 8; +DELETE FROM articles WHERE id = 8; + +# Case : Turn OFF stopword list variable and search stopword on NEW index. +# Drop index +ALTER TABLE articles DROP INDEX idx; +SHOW CREATE TABLE articles; + +# Create the FTS index Using Alter Table. +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); + +ANALYZE TABLE articles; + +# search default stopword with innodb_ft_enable_stopword is OFF. +# All records expected as stopwod filtering is OFF and we created +# new FTS index. +# (refer Behavior (at the top of the test) for explanation ) +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +# Update will succeed. +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); + +SELECT COUNT(*),max(id) FROM articles; +# Update the record - uncommet on fix +#UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +#WHERE id = 9; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +# Delete will succeed. +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 9; + + +DROP TABLE articles; + +SET SESSION innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=@innodb_ft_server_stopword_table_orig; +SET GLOBAL innodb_ft_user_stopword_table=@innodb_ft_user_stopword_table_orig; +SET SESSION innodb_ft_user_stopword_table=default; + +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT `idx` (title,body) + ) ENGINE=InnoDB; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL from Tutorial','DBMS stands for DataBase ...') , + ('when To Use MySQL Well','After that you went through a ...'), + ('where will Optimizing MySQL','In what tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# No records expeced for select +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +# Define a correct formated user stopword table +create table user_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +set session innodb_ft_user_stopword_table = "test/user_stopword"; +# Define a correct formated server stopword table +create table server_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +set global innodb_ft_server_stopword_table = "test/server_stopword"; +# Add values into user supplied stop word table +insert into user_stopword values("this"),("will"),("the"); + +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + +# Add values into server supplied stop word table +insert into server_stopword values("what"),("where"); +# Follwoing should return result as server stopword list was empty at create index time +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); + +# Delete stopword from user list +DELETE FROM user_stopword; +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# Follwoing should return result even though to server stopword list +# conatin these words. Session level stopword list takes priority +# Here user_stopword is set using innodb_ft_user_stopword_table +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); + +# Follwoing should return result as user stopword list was empty at create index time +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + +# Add values into user supplied stop word table +insert into user_stopword values("this"),("will"),("the"); + +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +SET SESSION innodb_ft_enable_stopword = 0; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + +# Session level stopword list takes priority +SET SESSION innodb_ft_enable_stopword = 1; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + +# Make user stopword list deafult so as to server stopword list takes priority +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table = default; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + + +DROP TABLE articles,user_stopword,server_stopword; + +# Restore Defaults +SET innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; +SET SESSION innodb_ft_user_stopword_table=default; + +#--------------------------------------------------------------------------------------- +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT `idx` (title,body) + ) ENGINE=InnoDB; + +SHOW CREATE TABLE articles; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL from Tutorial','DBMS stands for DataBase ...') , + ('when To Use MySQL Well','After that you went through a ...'), + ('where will Optimizing MySQL','In what tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# No records expeced for select +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +# Define a correct formated user stopword table +create table user_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +set session innodb_ft_user_stopword_table = "test/user_stopword"; +insert into user_stopword values("mysqld"),("DBMS"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); + + +# Drop existing index and create the FTS index Using Alter Table. +# user stopword list will take effect. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); + +# set user stopword list empty +set session innodb_ft_user_stopword_table = default; +# Define a correct formated user stopword table +create table server_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +set global innodb_ft_server_stopword_table = "test/server_stopword"; +insert into server_stopword values("root"),("properly"); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); + + +# set user stopword list empty +set session innodb_ft_user_stopword_table = "test/user_stopword"; +# The set operation should be successful +set global innodb_ft_server_stopword_table = "test/server_stopword"; +# user stopword list take effect as its session level +# Result expected for select +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); + +# set user stopword list +set session innodb_ft_user_stopword_table = "test/user_stopword"; +DELETE FROM user_stopword; +# The set operation should be successful +set global innodb_ft_server_stopword_table = "test/server_stopword"; +DELETE FROM server_stopword; +# user stopword list take affect as its session level +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); + +DROP TABLE articles,user_stopword,server_stopword; + +# Restore Values +SET SESSION innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; +SET SESSION innodb_ft_user_stopword_table=default; + + +#------------------------------------------------------------------------------ +# FTS stopword list test - check varaibles across sessions + +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT `idx` (title,body) + ) ENGINE=InnoDB; + +SHOW CREATE TABLE articles; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL from Tutorial','DBMS stands for DataBase ...') , + ('when To Use MySQL Well','After that you went through a ...'), + ('where will Optimizing MySQL','In what tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# session varaible innodb_ft_enable_stopword=0 will take effect for new FTS index +SET SESSION innodb_ft_enable_stopword = 0; +select @@innodb_ft_enable_stopword; + +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); + + +--echo "In connection 1" +--connection con1 +select @@innodb_ft_enable_stopword; + +ANALYZE TABLE articles; + +# result expected as index created before setting innodb_ft_enable_stopword varaible off +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + +SET SESSION innodb_ft_enable_stopword = 1; +select @@innodb_ft_enable_stopword; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# no result expected turned innodb_ft_enable_stopword is ON +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + + +--echo "In connection default" +--connection default +select @@innodb_ft_enable_stopword; +# no result expected as word not indexed from connection 1 +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); + +SET SESSION innodb_ft_enable_stopword = 1; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); + + +--echo "In connection 1" +--connection con1 +SET SESSION innodb_ft_enable_stopword = 1; +# Define a correct formated user stopword table +create table user_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +set session innodb_ft_user_stopword_table = "test/user_stopword"; +# Add values into user supplied stop word table +insert into user_stopword values("this"),("will"),("the"); +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# no result expected as innodb_ft_user_stopword_table filter it +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + + +--echo "In connection default" +--connection default +# no result expected as innodb_ft_user_stopword_table filter it from connection1 +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +select @@innodb_ft_user_stopword_table; +# Define a correct formated user stopword table +create table user_stopword_1(value varchar(30)) engine = innodb; +# The set operation should be successful +set session innodb_ft_user_stopword_table = "test/user_stopword_1"; +insert into user_stopword_1 values("when"); +SET SESSION innodb_ft_enable_stopword = 1; +# result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('when'); +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# no result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('when'); + +--echo "In connection 1" +--connection con1 +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table=default; +select @@innodb_ft_user_stopword_table; +select @@innodb_ft_server_stopword_table; +# Define a correct formated server stopword table +create table server_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +SET GLOBAL innodb_ft_server_stopword_table = "test/server_stopword"; +select @@innodb_ft_server_stopword_table; +insert into server_stopword values("when"),("the"); +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# no result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('the'); + +disconnect con1; +--source include/wait_until_disconnected.inc + +--echo "In connection default" +--connection default +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table=default; +select @@innodb_ft_server_stopword_table; +# result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); +insert into server_stopword values("where"),("will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# no result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('the'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); + + +DROP TABLE articles,user_stopword,user_stopword_1,server_stopword; + +# Restore Values +SET GLOBAL innodb_ft_user_stopword_table=@innodb_ft_user_stopword_table_orig; +SET GLOBAL innodb_ft_server_stopword_table=@innodb_ft_server_stopword_table_orig; diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index eabc554036a..a45a37a4b3c 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -176,7 +176,7 @@ get_buf_dump_dir() /* The dump file should be created in the default data directory if innodb_data_home_dir is set as an empty string. */ - if (strcmp(srv_data_home, "") == 0) { + if (!*srv_data_home) { dump_dir = fil_path_to_mysql_datadir; } else { dump_dir = srv_data_home; @@ -207,9 +207,11 @@ buf_dump( ulint i; int ret; + mysql_mutex_lock(&LOCK_global_system_variables); ut_snprintf(full_filename, sizeof(full_filename), "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR, srv_buf_dump_filename); + mysql_mutex_unlock(&LOCK_global_system_variables); ut_snprintf(tmp_filename, sizeof(tmp_filename), "%s.incomplete", full_filename); @@ -513,9 +515,11 @@ buf_load() /* Ignore any leftovers from before */ buf_load_abort_flag = FALSE; + mysql_mutex_lock(&LOCK_global_system_variables); ut_snprintf(full_filename, sizeof(full_filename), "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR, srv_buf_dump_filename); + mysql_mutex_unlock(&LOCK_global_system_variables); buf_load_status(STATUS_NOTICE, "Loading buffer pool(s) from %s", full_filename); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 6dbe5e0e2a0..54cf2f11884 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2019, MariaDB Corporation. +Copyright (c) 2016, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -443,9 +443,9 @@ fts_read_stopword( /******************************************************************//** Load user defined stopword from designated user table -@return TRUE if load operation is successful */ +@return whether the operation is successful */ static -ibool +bool fts_load_user_stopword( /*===================*/ fts_t* fts, /*!< in: FTS struct */ @@ -453,27 +453,26 @@ fts_load_user_stopword( name */ fts_stopword_t* stopword_info) /*!< in: Stopword info */ { - pars_info_t* info; - que_t* graph; - dberr_t error = DB_SUCCESS; - ibool ret = TRUE; - trx_t* trx; - ibool has_lock = fts->dict_locked; - - trx = trx_allocate_for_background(); - trx->op_info = "Load user stopword table into FTS cache"; - - if (!has_lock) { + if (!fts->dict_locked) { mutex_enter(&dict_sys->mutex); } - /* Validate the user table existence and in the right - format */ + /* Validate the user table existence in the right format */ + bool ret= false; stopword_info->charset = fts_valid_stopword_table(stopword_table_name); if (!stopword_info->charset) { - ret = FALSE; - goto cleanup; - } else if (!stopword_info->cached_stopword) { +cleanup: + if (!fts->dict_locked) { + mutex_exit(&dict_sys->mutex); + } + + return ret; + } + + trx_t* trx = trx_allocate_for_background(); + trx->op_info = "Load user stopword table into FTS cache"; + + if (!stopword_info->cached_stopword) { /* Create the stopword RB tree with the stopword column charset. All comparison will use this charset */ stopword_info->cached_stopword = rbt_create_arg_cmp( @@ -482,14 +481,14 @@ fts_load_user_stopword( } - info = pars_info_create(); + pars_info_t* info = pars_info_create(); pars_info_bind_id(info, TRUE, "table_stopword", stopword_table_name); pars_info_bind_function(info, "my_func", fts_read_stopword, stopword_info); - graph = fts_parse_sql_no_dict_lock( + que_t* graph = fts_parse_sql_no_dict_lock( NULL, info, "DECLARE FUNCTION my_func;\n" @@ -508,14 +507,13 @@ fts_load_user_stopword( "CLOSE c;"); for (;;) { - error = fts_eval_sql(trx, graph); + dberr_t error = fts_eval_sql(trx, graph); if (error == DB_SUCCESS) { fts_sql_commit(trx); stopword_info->status = STOPWORD_USER_TABLE; break; } else { - fts_sql_rollback(trx); ut_print_timestamp(stderr); @@ -537,14 +535,9 @@ fts_load_user_stopword( } que_graph_free(graph); - -cleanup: - if (!has_lock) { - mutex_exit(&dict_sys->mutex); - } - trx_free_for_background(trx); - return(ret); + ret = true; + goto cleanup; } /******************************************************************//** @@ -3495,8 +3488,8 @@ fts_add_doc_by_id( if (table->fts->cache->stopword_info.status & STOPWORD_NOT_INIT) { - fts_load_stopword(table, NULL, NULL, - NULL, TRUE, TRUE); + fts_load_stopword(table, NULL, + NULL, true, true); } fts_cache_add_doc( @@ -7244,21 +7237,19 @@ This function loads the stopword into the FTS cache. It also records/fetches stopword configuration to/from FTS configure table, depending on whether we are creating or reloading the FTS. -@return TRUE if load operation is successful */ +@return true if load operation is successful */ UNIV_INTERN -ibool +bool fts_load_stopword( /*==============*/ const dict_table_t* table, /*!< in: Table with FTS */ trx_t* trx, /*!< in: Transactions */ - const char* global_stopword_table, /*!< in: Global stopword table - name */ const char* session_stopword_table, /*!< in: Session stopword table name */ - ibool stopword_is_on, /*!< in: Whether stopword + bool stopword_is_on, /*!< in: Whether stopword option is turned on/off */ - ibool reload) /*!< in: Whether it is + bool reload) /*!< in: Whether it is for reloading FTS table */ { fts_table_t fts_table; @@ -7274,9 +7265,8 @@ fts_load_stopword( cache = table->fts->cache; - if (!reload && !(cache->stopword_info.status - & STOPWORD_NOT_INIT)) { - return(TRUE); + if (!reload && !(cache->stopword_info.status & STOPWORD_NOT_INIT)) { + return true; } if (!trx) { @@ -7321,12 +7311,11 @@ fts_load_stopword( goto cleanup; } - if (strlen((char*) str.f_str) > 0) { + if (*str.f_str) { stopword_to_use = (const char*) str.f_str; } } else { - stopword_to_use = (session_stopword_table) - ? session_stopword_table : global_stopword_table; + stopword_to_use = session_stopword_table; } if (stopword_to_use @@ -7363,7 +7352,7 @@ cleanup: sizeof(fts_tokenizer_word_t), fts_utf8_string_cmp); } - return(error == DB_SUCCESS); + return error == DB_SUCCESS; } /**********************************************************************//** @@ -7569,7 +7558,7 @@ fts_init_index( } else { if (table->fts->cache->stopword_info.status & STOPWORD_NOT_INIT) { - fts_load_stopword(table, NULL, NULL, NULL, TRUE, TRUE); + fts_load_stopword(table, NULL, NULL, true, true); } for (ulint i = 0; i < ib_vector_size(cache->get_docs); ++i) { diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a1505eecd29..c54dae220ae 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -11508,10 +11508,17 @@ innobase_fts_load_stopword( trx_t* trx, /*!< in: transaction */ THD* thd) /*!< in: current thread */ { - return(fts_load_stopword(table, trx, - innobase_server_stopword_table, - THDVAR(thd, ft_user_stopword_table), - THDVAR(thd, ft_enable_stopword), FALSE)); + const char *stopword_table= THDVAR(thd, ft_user_stopword_table); + if (!stopword_table) + { + mysql_mutex_lock(&LOCK_global_system_variables); + if (innobase_server_stopword_table) + stopword_table= thd_strdup(thd, innobase_server_stopword_table); + mysql_mutex_unlock(&LOCK_global_system_variables); + } + + return fts_load_stopword(table, trx, stopword_table, + THDVAR(thd, ft_enable_stopword), false); } /*****************************************************************//** @@ -17054,7 +17061,6 @@ innodb_stopword_table_validate( char buff[STRING_BUFFER_USUAL_SIZE]; int len = sizeof(buff); trx_t* trx; - int ret = 1; ut_a(save != NULL); ut_a(value != NULL); @@ -17067,14 +17073,22 @@ innodb_stopword_table_validate( /* Validate the stopword table's (if supplied) existence and of the right format */ - if (!stopword_table_name - || fts_valid_stopword_table(stopword_table_name)) { - *static_cast(save) = stopword_table_name; - ret = 0; - } + int ret = stopword_table_name && !fts_valid_stopword_table( + stopword_table_name); row_mysql_unlock_data_dictionary(trx); + if (!ret) { + if (stopword_table_name == buff) { + ut_ad(static_cast(len) < sizeof buff); + stopword_table_name = thd_strmake(thd, + stopword_table_name, + len); + } + + *static_cast(save) = stopword_table_name; + } + return(ret); } @@ -17082,9 +17096,10 @@ innodb_stopword_table_validate( static char* innodb_ft_aux_table; /** Update innodb_ft_aux_table_id on SET GLOBAL innodb_ft_aux_table. +@param[in,out] thd connection @param[out] save new value of innodb_ft_aux_table @param[in] value user-specified value */ -static int innodb_ft_aux_table_validate(THD*, st_mysql_sys_var*, +static int innodb_ft_aux_table_validate(THD *thd, st_mysql_sys_var*, void* save, st_mysql_value* value) { char buf[STRING_BUFFER_USUAL_SIZE]; @@ -17098,6 +17113,15 @@ static int innodb_ft_aux_table_validate(THD*, st_mysql_sys_var*, dict_table_close(table, FALSE, FALSE); if (id) { innodb_ft_aux_table_id = id; + if (table_name == buf) { + ut_ad(static_cast(len) + < sizeof buf); + table_name = thd_strmake(thd, + table_name, + len); + } + + *static_cast(save) = table_name; return 0; } @@ -17796,52 +17820,43 @@ exit: return; } -#ifdef __WIN__ -/*************************************************************//** -Validate if passed-in "value" is a valid value for -innodb_buffer_pool_filename. On Windows, file names with colon (:) -are not allowed. - +/** Validate SET GLOBAL innodb_buffer_pool_filename. +On Windows, file names with colon (:) are not allowed. +@param thd connection +@param save &srv_buf_dump_filename +@param value new value to be validated @return 0 for valid name */ -static -int -innodb_srv_buf_dump_filename_validate( -/*==================================*/ - THD* thd, /*!< in: thread handle */ - struct st_mysql_sys_var* var, /*!< in: pointer to system - variable */ - void* save, /*!< out: immediate result - for update function */ - struct st_mysql_value* value) /*!< in: incoming string */ +static int innodb_srv_buf_dump_filename_validate(THD *thd, st_mysql_sys_var*, + void *save, + st_mysql_value *value) { - const char* buf_name; - char buff[OS_FILE_MAX_PATH]; - int len= sizeof(buff); + char buff[OS_FILE_MAX_PATH]; + int len= sizeof buff; - ut_a(save != NULL); - ut_a(value != NULL); - - buf_name = value->val_str(value, buff, &len); - - if (buf_name) { - if (is_filename_allowed(buf_name, len, FALSE)){ - *static_cast(save) = buf_name; - return(0); - } else { - push_warning_printf(thd, - Sql_condition::WARN_LEVEL_WARN, - ER_WRONG_ARGUMENTS, - "InnoDB: innodb_buffer_pool_filename " - "cannot have colon (:) in the file name."); - - } - } - - return(1); -} -#else /* __WIN__ */ -# define innodb_srv_buf_dump_filename_validate NULL + if (const char *buf_name= value->val_str(value, buff, &len)) + { +#ifdef __WIN__ + if (!is_filename_allowed(buf_name, len, FALSE)) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: innodb_buffer_pool_filename " + "cannot have colon (:) in the file name."); + return 1; + } #endif /* __WIN__ */ + if (buf_name == buff) + { + ut_ad(static_cast(len) < sizeof buff); + buf_name= thd_strmake(thd, buf_name, len); + } + + *static_cast(save)= buf_name; + return 0; + } + + return 1; +} #ifdef UNIV_DEBUG static char* srv_buffer_pool_evict; diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index 3beddd68722..886ac257f01 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2019, MariaDB Corporation. +Copyright (c) 2016, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -899,21 +899,19 @@ fts_valid_stopword_table( name */ /****************************************************************//** This function loads specified stopword into FTS cache -@return TRUE if success */ +@return true if success */ UNIV_INTERN -ibool +bool fts_load_stopword( /*==============*/ const dict_table_t* table, /*!< in: Table with FTS */ trx_t* trx, /*!< in: Transaction */ - const char* global_stopword_table, /*!< in: Global stopword table - name */ const char* session_stopword_table, /*!< in: Session stopword table name */ - ibool stopword_is_on, /*!< in: Whether stopword + bool stopword_is_on, /*!< in: Whether stopword option is turned on/off */ - ibool reload); /*!< in: Whether it is during + bool reload); /*!< in: Whether it is during reload of FTS table */ /****************************************************************//** diff --git a/storage/xtradb/buf/buf0dump.cc b/storage/xtradb/buf/buf0dump.cc index 349e7d45ab8..20dec30d106 100644 --- a/storage/xtradb/buf/buf0dump.cc +++ b/storage/xtradb/buf/buf0dump.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -176,7 +176,7 @@ get_buf_dump_dir() /* The dump file should be created in the default data directory if innodb_data_home_dir is set as an empty string. */ - if (strcmp(srv_data_home, "") == 0) { + if (!*srv_data_home) { dump_dir = fil_path_to_mysql_datadir; } else { dump_dir = srv_data_home; @@ -208,9 +208,11 @@ buf_dump( ulint i; int ret; + mysql_mutex_lock(&LOCK_global_system_variables); ut_snprintf(full_filename, sizeof(full_filename), "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR, srv_buf_dump_filename); + mysql_mutex_unlock(&LOCK_global_system_variables); ut_snprintf(tmp_filename, sizeof(tmp_filename), format_name, full_filename); @@ -514,9 +516,11 @@ buf_load() /* Ignore any leftovers from before */ buf_load_abort_flag = FALSE; + mysql_mutex_lock(&LOCK_global_system_variables); ut_snprintf(full_filename, sizeof(full_filename), "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR, srv_buf_dump_filename); + mysql_mutex_unlock(&LOCK_global_system_variables); buf_load_status(STATUS_NOTICE, "Loading buffer pool(s) from %s", full_filename); diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc index 6dbe5e0e2a0..54cf2f11884 100644 --- a/storage/xtradb/fts/fts0fts.cc +++ b/storage/xtradb/fts/fts0fts.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2019, MariaDB Corporation. +Copyright (c) 2016, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -443,9 +443,9 @@ fts_read_stopword( /******************************************************************//** Load user defined stopword from designated user table -@return TRUE if load operation is successful */ +@return whether the operation is successful */ static -ibool +bool fts_load_user_stopword( /*===================*/ fts_t* fts, /*!< in: FTS struct */ @@ -453,27 +453,26 @@ fts_load_user_stopword( name */ fts_stopword_t* stopword_info) /*!< in: Stopword info */ { - pars_info_t* info; - que_t* graph; - dberr_t error = DB_SUCCESS; - ibool ret = TRUE; - trx_t* trx; - ibool has_lock = fts->dict_locked; - - trx = trx_allocate_for_background(); - trx->op_info = "Load user stopword table into FTS cache"; - - if (!has_lock) { + if (!fts->dict_locked) { mutex_enter(&dict_sys->mutex); } - /* Validate the user table existence and in the right - format */ + /* Validate the user table existence in the right format */ + bool ret= false; stopword_info->charset = fts_valid_stopword_table(stopword_table_name); if (!stopword_info->charset) { - ret = FALSE; - goto cleanup; - } else if (!stopword_info->cached_stopword) { +cleanup: + if (!fts->dict_locked) { + mutex_exit(&dict_sys->mutex); + } + + return ret; + } + + trx_t* trx = trx_allocate_for_background(); + trx->op_info = "Load user stopword table into FTS cache"; + + if (!stopword_info->cached_stopword) { /* Create the stopword RB tree with the stopword column charset. All comparison will use this charset */ stopword_info->cached_stopword = rbt_create_arg_cmp( @@ -482,14 +481,14 @@ fts_load_user_stopword( } - info = pars_info_create(); + pars_info_t* info = pars_info_create(); pars_info_bind_id(info, TRUE, "table_stopword", stopword_table_name); pars_info_bind_function(info, "my_func", fts_read_stopword, stopword_info); - graph = fts_parse_sql_no_dict_lock( + que_t* graph = fts_parse_sql_no_dict_lock( NULL, info, "DECLARE FUNCTION my_func;\n" @@ -508,14 +507,13 @@ fts_load_user_stopword( "CLOSE c;"); for (;;) { - error = fts_eval_sql(trx, graph); + dberr_t error = fts_eval_sql(trx, graph); if (error == DB_SUCCESS) { fts_sql_commit(trx); stopword_info->status = STOPWORD_USER_TABLE; break; } else { - fts_sql_rollback(trx); ut_print_timestamp(stderr); @@ -537,14 +535,9 @@ fts_load_user_stopword( } que_graph_free(graph); - -cleanup: - if (!has_lock) { - mutex_exit(&dict_sys->mutex); - } - trx_free_for_background(trx); - return(ret); + ret = true; + goto cleanup; } /******************************************************************//** @@ -3495,8 +3488,8 @@ fts_add_doc_by_id( if (table->fts->cache->stopword_info.status & STOPWORD_NOT_INIT) { - fts_load_stopword(table, NULL, NULL, - NULL, TRUE, TRUE); + fts_load_stopword(table, NULL, + NULL, true, true); } fts_cache_add_doc( @@ -7244,21 +7237,19 @@ This function loads the stopword into the FTS cache. It also records/fetches stopword configuration to/from FTS configure table, depending on whether we are creating or reloading the FTS. -@return TRUE if load operation is successful */ +@return true if load operation is successful */ UNIV_INTERN -ibool +bool fts_load_stopword( /*==============*/ const dict_table_t* table, /*!< in: Table with FTS */ trx_t* trx, /*!< in: Transactions */ - const char* global_stopword_table, /*!< in: Global stopword table - name */ const char* session_stopword_table, /*!< in: Session stopword table name */ - ibool stopword_is_on, /*!< in: Whether stopword + bool stopword_is_on, /*!< in: Whether stopword option is turned on/off */ - ibool reload) /*!< in: Whether it is + bool reload) /*!< in: Whether it is for reloading FTS table */ { fts_table_t fts_table; @@ -7274,9 +7265,8 @@ fts_load_stopword( cache = table->fts->cache; - if (!reload && !(cache->stopword_info.status - & STOPWORD_NOT_INIT)) { - return(TRUE); + if (!reload && !(cache->stopword_info.status & STOPWORD_NOT_INIT)) { + return true; } if (!trx) { @@ -7321,12 +7311,11 @@ fts_load_stopword( goto cleanup; } - if (strlen((char*) str.f_str) > 0) { + if (*str.f_str) { stopword_to_use = (const char*) str.f_str; } } else { - stopword_to_use = (session_stopword_table) - ? session_stopword_table : global_stopword_table; + stopword_to_use = session_stopword_table; } if (stopword_to_use @@ -7363,7 +7352,7 @@ cleanup: sizeof(fts_tokenizer_word_t), fts_utf8_string_cmp); } - return(error == DB_SUCCESS); + return error == DB_SUCCESS; } /**********************************************************************//** @@ -7569,7 +7558,7 @@ fts_init_index( } else { if (table->fts->cache->stopword_info.status & STOPWORD_NOT_INIT) { - fts_load_stopword(table, NULL, NULL, NULL, TRUE, TRUE); + fts_load_stopword(table, NULL, NULL, true, true); } for (ulint i = 0; i < ib_vector_size(cache->get_docs); ++i) { diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 1593bf8ab46..c57870915dc 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -12056,10 +12056,17 @@ innobase_fts_load_stopword( trx_t* trx, /*!< in: transaction */ THD* thd) /*!< in: current thread */ { - return(fts_load_stopword(table, trx, - innobase_server_stopword_table, - THDVAR(thd, ft_user_stopword_table), - THDVAR(thd, ft_enable_stopword), FALSE)); + const char *stopword_table= THDVAR(thd, ft_user_stopword_table); + if (!stopword_table) + { + mysql_mutex_lock(&LOCK_global_system_variables); + if (innobase_server_stopword_table) + stopword_table= thd_strdup(thd, innobase_server_stopword_table); + mysql_mutex_unlock(&LOCK_global_system_variables); + } + + return fts_load_stopword(table, trx, stopword_table, + THDVAR(thd, ft_enable_stopword), false); } /*****************************************************************//** @@ -17766,7 +17773,6 @@ innodb_stopword_table_validate( char buff[STRING_BUFFER_USUAL_SIZE]; int len = sizeof(buff); trx_t* trx; - int ret = 1; ut_a(save != NULL); ut_a(value != NULL); @@ -17779,14 +17785,22 @@ innodb_stopword_table_validate( /* Validate the stopword table's (if supplied) existence and of the right format */ - if (!stopword_table_name - || fts_valid_stopword_table(stopword_table_name)) { - *static_cast(save) = stopword_table_name; - ret = 0; - } + int ret = stopword_table_name && !fts_valid_stopword_table( + stopword_table_name); row_mysql_unlock_data_dictionary(trx); + if (!ret) { + if (stopword_table_name == buff) { + ut_ad(static_cast(len) < sizeof buff); + stopword_table_name = thd_strmake(thd, + stopword_table_name, + len); + } + + *static_cast(save) = stopword_table_name; + } + return(ret); } @@ -17794,9 +17808,10 @@ innodb_stopword_table_validate( static char* innodb_ft_aux_table; /** Update innodb_ft_aux_table_id on SET GLOBAL innodb_ft_aux_table. +@param[in,out] thd connection @param[out] save new value of innodb_ft_aux_table @param[in] value user-specified value */ -static int innodb_ft_aux_table_validate(THD*, st_mysql_sys_var*, +static int innodb_ft_aux_table_validate(THD *thd, st_mysql_sys_var*, void* save, st_mysql_value* value) { char buf[STRING_BUFFER_USUAL_SIZE]; @@ -17810,6 +17825,15 @@ static int innodb_ft_aux_table_validate(THD*, st_mysql_sys_var*, dict_table_close(table, FALSE, FALSE); if (id) { innodb_ft_aux_table_id = id; + if (table_name == buf) { + ut_ad(static_cast(len) + < sizeof buf); + table_name = thd_strmake(thd, + table_name, + len); + } + + *static_cast(save) = table_name; return 0; } @@ -18508,52 +18532,43 @@ exit: return; } -#ifdef __WIN__ -/*************************************************************//** -Validate if passed-in "value" is a valid value for -innodb_buffer_pool_filename. On Windows, file names with colon (:) -are not allowed. - +/** Validate SET GLOBAL innodb_buffer_pool_filename. +On Windows, file names with colon (:) are not allowed. +@param thd connection +@param save &srv_buf_dump_filename +@param value new value to be validated @return 0 for valid name */ -static -int -innodb_srv_buf_dump_filename_validate( -/*==================================*/ - THD* thd, /*!< in: thread handle */ - struct st_mysql_sys_var* var, /*!< in: pointer to system - variable */ - void* save, /*!< out: immediate result - for update function */ - struct st_mysql_value* value) /*!< in: incoming string */ +static int innodb_srv_buf_dump_filename_validate(THD *thd, st_mysql_sys_var*, + void *save, + st_mysql_value *value) { - const char* buf_name; - char buff[OS_FILE_MAX_PATH]; - int len= sizeof(buff); + char buff[OS_FILE_MAX_PATH]; + int len= sizeof buff; - ut_a(save != NULL); - ut_a(value != NULL); - - buf_name = value->val_str(value, buff, &len); - - if (buf_name) { - if (is_filename_allowed(buf_name, len, FALSE)){ - *static_cast(save) = buf_name; - return(0); - } else { - push_warning_printf(thd, - Sql_condition::WARN_LEVEL_WARN, - ER_WRONG_ARGUMENTS, - "InnoDB: innodb_buffer_pool_filename " - "cannot have colon (:) in the file name."); - - } - } - - return(1); -} -#else /* __WIN__ */ -# define innodb_srv_buf_dump_filename_validate NULL + if (const char *buf_name= value->val_str(value, buff, &len)) + { +#ifdef __WIN__ + if (!is_filename_allowed(buf_name, len, FALSE)) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: innodb_buffer_pool_filename " + "cannot have colon (:) in the file name."); + return 1; + } #endif /* __WIN__ */ + if (buf_name == buff) + { + ut_ad(static_cast(len) < sizeof buff); + buf_name= thd_strmake(thd, buf_name, len); + } + + *static_cast(save)= buf_name; + return 0; + } + + return 1; +} #ifdef UNIV_DEBUG static char* srv_buffer_pool_evict; diff --git a/storage/xtradb/include/fts0fts.h b/storage/xtradb/include/fts0fts.h index 714f811db27..4d07ac1612f 100644 --- a/storage/xtradb/include/fts0fts.h +++ b/storage/xtradb/include/fts0fts.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2019, MariaDB Corporation. +Copyright (c) 2016, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -899,21 +899,19 @@ fts_valid_stopword_table( name */ /****************************************************************//** This function loads specified stopword into FTS cache -@return TRUE if success */ +@return true if success */ UNIV_INTERN -ibool +bool fts_load_stopword( /*==============*/ const dict_table_t* table, /*!< in: Table with FTS */ trx_t* trx, /*!< in: Transaction */ - const char* global_stopword_table, /*!< in: Global stopword table - name */ const char* session_stopword_table, /*!< in: Session stopword table name */ - ibool stopword_is_on, /*!< in: Whether stopword + bool stopword_is_on, /*!< in: Whether stopword option is turned on/off */ - ibool reload); /*!< in: Whether it is during + bool reload); /*!< in: Whether it is during reload of FTS table */ /****************************************************************//** From 503fd2115bdc79f0b005917e058855411fdeb691 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 27 Apr 2020 15:05:18 +0200 Subject: [PATCH 28/35] fix the test for windows --- mysql-test/main/grant_repair.result | 2 +- mysql-test/main/grant_repair.test | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/grant_repair.result b/mysql-test/main/grant_repair.result index afadca78db7..d97bcc38a08 100644 --- a/mysql-test/main/grant_repair.result +++ b/mysql-test/main/grant_repair.result @@ -1,4 +1,4 @@ -call mtr.add_suppression("/mysql/user"); +call mtr.add_suppression("mysql.user"); # switching from mysql.global_priv to mysql.user flush tables; flush privileges; diff --git a/mysql-test/main/grant_repair.test b/mysql-test/main/grant_repair.test index 0fc0edc7ded..f07e4df3ae6 100644 --- a/mysql-test/main/grant_repair.test +++ b/mysql-test/main/grant_repair.test @@ -1,8 +1,9 @@ # # MDEV-20257 Server crashes in Grant_table_base::init_read_record upon crash-upgrade # +source include/not_embedded.inc; -call mtr.add_suppression("/mysql/user"); +call mtr.add_suppression("mysql.user"); source include/switch_to_mysql_user.inc; let mysql_datadir=`select @@datadir`; @@ -14,6 +15,7 @@ perl; sysseek F, 24, O_RDWR or die "sysseek: $!"; syswrite F, 1, 1 or die "syswrite: $!"; EOF +replace_result \\ /; flush privileges; source include/switch_to_mysql_global_priv.inc; From 01f8f33b43e5aa63752ccd71a6a63c5840207d3c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 23 Apr 2020 12:25:15 +0200 Subject: [PATCH 29/35] MDEV-21913 Add pam_user_map.so file to binary tarball package --- cmake/install_layout.cmake | 4 ++++ plugin/auth_pam/CMakeLists.txt | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cmake/install_layout.cmake b/cmake/install_layout.cmake index e9413390172..b2d9b7734ce 100644 --- a/cmake/install_layout.cmake +++ b/cmake/install_layout.cmake @@ -128,6 +128,8 @@ SET(INSTALL_SUPPORTFILESDIR_STANDALONE "support-files") SET(INSTALL_MYSQLDATADIR_STANDALONE "data") SET(INSTALL_UNIX_ADDRDIR_STANDALONE "/tmp/mysql.sock") +SET(INSTALL_PAMDIR_STANDALONE "share") +SET(INSTALL_PAMDATADIR_STANDALONE "share") # # RPM layout # @@ -164,6 +166,7 @@ SET(INSTALL_SYSTEMD_UNITDIR_RPM "/usr/lib/systemd/system") SET(INSTALL_SYSTEMD_SYSUSERSDIR_RPM "/usr/lib/sysusers.d") SET(INSTALL_SYSTEMD_TMPFILESDIR_RPM "/usr/lib/tmpfiles.d") SET(INSTALL_PAMDIR_RPM "/${INSTALL_LIBDIR_RPM}/security") +SET(INSTALL_PAMDATADIR_RPM "/etc/security") # # DEB layout @@ -197,6 +200,7 @@ SET(INSTALL_SYSTEMD_UNITDIR_DEB "/lib/systemd/system") SET(INSTALL_SYSTEMD_SYSUSERSDIR_DEB "/usr/lib/sysusers.d") SET(INSTALL_SYSTEMD_TMPFILESDIR_DEB "/usr/lib/tmpfiles.d") SET(INSTALL_PAMDIR_DEB "/lib/${CMAKE_CXX_LIBRARY_ARCHITECTURE}/security") +SET(INSTALL_PAMDATADIR_DEB "/etc/security") # # SVR4 layout diff --git a/plugin/auth_pam/CMakeLists.txt b/plugin/auth_pam/CMakeLists.txt index c826b422240..ac598e4ffa6 100644 --- a/plugin/auth_pam/CMakeLists.txt +++ b/plugin/auth_pam/CMakeLists.txt @@ -22,7 +22,7 @@ IF(HAVE_PAM_APPL_H) IF(HAVE_STRNDUP) ADD_DEFINITIONS(-DHAVE_STRNDUP) ENDIF(HAVE_STRNDUP) - FIND_LIBRARY(PAM_LIBRARY pam) + FIND_LIBRARY(PAM_LIBRARY pam) # for srpm build-depends detection MYSQL_ADD_PLUGIN(auth_pam auth_pam.c LINK_LIBRARIES pam MODULE_ONLY) IF(TARGET auth_pam) @@ -31,7 +31,7 @@ IF(HAVE_PAM_APPL_H) SET_TARGET_PROPERTIES (pam_user_map PROPERTIES PREFIX "") IF(INSTALL_PAMDIR) INSTALL(TARGETS pam_user_map DESTINATION ${INSTALL_PAMDIR} COMPONENT Server) - INSTALL(FILES mapper/user_map.conf DESTINATION /etc/security COMPONENT Server) + INSTALL(FILES mapper/user_map.conf DESTINATION ${INSTALL_PAMDATADIR} COMPONENT Server) ENDIF() ENDIF() ENDIF(HAVE_PAM_APPL_H) From fb7c1b9415c9a8b0dc2e86ae44f0e7a2634e5d7e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 22 Apr 2020 15:39:40 +0200 Subject: [PATCH 30/35] MDEV-21331 installation fails on a server with containers when detecting running mysqld processes to stop, ignore processes in different namespaces. --- debian/mariadb-server-10.2.preinst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/mariadb-server-10.2.preinst b/debian/mariadb-server-10.2.preinst index ed987507d18..161d9caee6e 100644 --- a/debian/mariadb-server-10.2.preinst +++ b/debian/mariadb-server-10.2.preinst @@ -25,7 +25,7 @@ stop_server() { # Return immediately if there are no mysql processes running # as there is no point in trying to shutdown in that case. - if ! pgrep mysqld > /dev/null; then return; fi + if ! pgrep --ns $$ mysqld > /dev/null; then return; fi set +e if [ -x /usr/sbin/invoke-rc.d ]; then From fae70d6b1c65c249c6b2927f1461f22b867a605c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Apr 2020 09:47:40 +0300 Subject: [PATCH 31/35] Cleanup: Declare rtr_get_father_node() statically --- storage/innobase/gis/gis0sea.cc | 234 +++++++++++++-------------- storage/innobase/include/gis0rtree.h | 18 +-- 2 files changed, 117 insertions(+), 135 deletions(-) diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 7ac529ed0db..e0dde1154b0 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2016, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -686,6 +686,121 @@ rtr_page_get_father( mem_heap_free(heap); } +/********************************************************************//** +Returns the upper level node pointer to a R-Tree page. It is assumed +that mtr holds an x-latch on the tree. */ +static void rtr_get_father_node( + dict_index_t* index, /*!< in: index */ + ulint level, /*!< in: the tree level of search */ + const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in + tuple must be set so that it cannot get + compared to the node ptr page number field! */ + btr_cur_t* sea_cur,/*!< in: search cursor */ + btr_cur_t* btr_cur,/*!< in/out: tree cursor; the cursor page is + s- or x-latched, but see also above! */ + ulint page_no,/*!< Current page no */ + mtr_t* mtr) /*!< in: mtr */ +{ + mem_heap_t* heap = NULL; + bool ret = false; + const rec_t* rec; + ulint n_fields; + bool new_rtr = false; + + /* Try to optimally locate the parent node. Level should always + less than sea_cur->tree_height unless the root is splitting */ + if (sea_cur && sea_cur->tree_height > level) { + + ut_ad(mtr_memo_contains_flagged(mtr, + dict_index_get_lock(index), + MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); + ret = rtr_cur_restore_position( + BTR_CONT_MODIFY_TREE, sea_cur, level, mtr); + + /* Once we block shrink tree nodes while there are + active search on it, this optimal locating should always + succeeds */ + ut_ad(ret); + + if (ret) { + btr_pcur_t* r_cursor = rtr_get_parent_cursor( + sea_cur, level, false); + + rec = btr_pcur_get_rec(r_cursor); + + ut_ad(r_cursor->rel_pos == BTR_PCUR_ON); + page_cur_position(rec, + btr_pcur_get_block(r_cursor), + btr_cur_get_page_cur(btr_cur)); + btr_cur->rtr_info = sea_cur->rtr_info; + btr_cur->tree_height = sea_cur->tree_height; + ut_ad(rtr_compare_cursor_rec( + index, btr_cur, page_no, &heap)); + goto func_exit; + } + } + + /* We arrive here in one of two scenario + 1) check table and btr_valide + 2) index root page being raised */ + ut_ad(!sea_cur || sea_cur->tree_height == level); + + if (btr_cur->rtr_info) { + rtr_clean_rtr_info(btr_cur->rtr_info, true); + } else { + new_rtr = true; + } + + btr_cur->rtr_info = rtr_create_rtr_info(false, false, btr_cur, index); + + if (sea_cur && sea_cur->tree_height == level) { + /* root split, and search the new root */ + btr_cur_search_to_nth_level( + index, level, tuple, PAGE_CUR_RTREE_LOCATE, + BTR_CONT_MODIFY_TREE, btr_cur, 0, + __FILE__, __LINE__, mtr); + + } else { + /* btr_validate */ + ut_ad(level >= 1); + ut_ad(!sea_cur); + + btr_cur_search_to_nth_level( + index, level, tuple, PAGE_CUR_RTREE_LOCATE, + BTR_CONT_MODIFY_TREE, btr_cur, 0, + __FILE__, __LINE__, mtr); + + rec = btr_cur_get_rec(btr_cur); + n_fields = dtuple_get_n_fields_cmp(tuple); + + if (page_rec_is_infimum(rec) + || (btr_cur->low_match != n_fields)) { + ret = rtr_pcur_getnext_from_path( + tuple, PAGE_CUR_RTREE_LOCATE, btr_cur, + level, BTR_CONT_MODIFY_TREE, + true, mtr); + + ut_ad(ret && btr_cur->low_match == n_fields); + } + } + + ret = rtr_compare_cursor_rec( + index, btr_cur, page_no, &heap); + + ut_ad(ret); + +func_exit: + if (heap) { + mem_heap_free(heap); + } + + if (new_rtr && btr_cur->rtr_info) { + rtr_clean_rtr_info(btr_cur->rtr_info, true); + btr_cur->rtr_info = NULL; + } +} + /** Returns the upper level node pointer to a R-Tree page. It is assumed that mtr holds an SX-latch or X-latch on the tree. @return rec_get_offsets() of the node pointer record */ @@ -806,123 +921,6 @@ rtr_page_get_father_block( cursor, mtr)); } -/********************************************************************//** -Returns the upper level node pointer to a R-Tree page. It is assumed -that mtr holds an x-latch on the tree. */ -void -rtr_get_father_node( -/*================*/ - dict_index_t* index, /*!< in: index */ - ulint level, /*!< in: the tree level of search */ - const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in - tuple must be set so that it cannot get - compared to the node ptr page number field! */ - btr_cur_t* sea_cur,/*!< in: search cursor */ - btr_cur_t* btr_cur,/*!< in/out: tree cursor; the cursor page is - s- or x-latched, but see also above! */ - ulint page_no,/*!< Current page no */ - mtr_t* mtr) /*!< in: mtr */ -{ - mem_heap_t* heap = NULL; - bool ret = false; - const rec_t* rec; - ulint n_fields; - bool new_rtr = false; - - /* Try to optimally locate the parent node. Level should always - less than sea_cur->tree_height unless the root is splitting */ - if (sea_cur && sea_cur->tree_height > level) { - - ut_ad(mtr_memo_contains_flagged(mtr, - dict_index_get_lock(index), - MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); - ret = rtr_cur_restore_position( - BTR_CONT_MODIFY_TREE, sea_cur, level, mtr); - - /* Once we block shrink tree nodes while there are - active search on it, this optimal locating should always - succeeds */ - ut_ad(ret); - - if (ret) { - btr_pcur_t* r_cursor = rtr_get_parent_cursor( - sea_cur, level, false); - - rec = btr_pcur_get_rec(r_cursor); - - ut_ad(r_cursor->rel_pos == BTR_PCUR_ON); - page_cur_position(rec, - btr_pcur_get_block(r_cursor), - btr_cur_get_page_cur(btr_cur)); - btr_cur->rtr_info = sea_cur->rtr_info; - btr_cur->tree_height = sea_cur->tree_height; - ut_ad(rtr_compare_cursor_rec( - index, btr_cur, page_no, &heap)); - goto func_exit; - } - } - - /* We arrive here in one of two scenario - 1) check table and btr_valide - 2) index root page being raised */ - ut_ad(!sea_cur || sea_cur->tree_height == level); - - if (btr_cur->rtr_info) { - rtr_clean_rtr_info(btr_cur->rtr_info, true); - } else { - new_rtr = true; - } - - btr_cur->rtr_info = rtr_create_rtr_info(false, false, btr_cur, index); - - if (sea_cur && sea_cur->tree_height == level) { - /* root split, and search the new root */ - btr_cur_search_to_nth_level( - index, level, tuple, PAGE_CUR_RTREE_LOCATE, - BTR_CONT_MODIFY_TREE, btr_cur, 0, - __FILE__, __LINE__, mtr); - - } else { - /* btr_validate */ - ut_ad(level >= 1); - ut_ad(!sea_cur); - - btr_cur_search_to_nth_level( - index, level, tuple, PAGE_CUR_RTREE_LOCATE, - BTR_CONT_MODIFY_TREE, btr_cur, 0, - __FILE__, __LINE__, mtr); - - rec = btr_cur_get_rec(btr_cur); - n_fields = dtuple_get_n_fields_cmp(tuple); - - if (page_rec_is_infimum(rec) - || (btr_cur->low_match != n_fields)) { - ret = rtr_pcur_getnext_from_path( - tuple, PAGE_CUR_RTREE_LOCATE, btr_cur, - level, BTR_CONT_MODIFY_TREE, - true, mtr); - - ut_ad(ret && btr_cur->low_match == n_fields); - } - } - - ret = rtr_compare_cursor_rec( - index, btr_cur, page_no, &heap); - - ut_ad(ret); - -func_exit: - if (heap) { - mem_heap_free(heap); - } - - if (new_rtr && btr_cur->rtr_info) { - rtr_clean_rtr_info(btr_cur->rtr_info, true); - btr_cur->rtr_info = NULL; - } -} - /*******************************************************************//** Create a RTree search info structure */ rtr_info_t* diff --git a/storage/innobase/include/gis0rtree.h b/storage/innobase/include/gis0rtree.h index ffb6beb922b..028014970f1 100644 --- a/storage/innobase/include/gis0rtree.h +++ b/storage/innobase/include/gis0rtree.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -166,22 +166,6 @@ rtr_ins_enlarge_mbr( que_thr_t* thr, /*!< in: query thread */ mtr_t* mtr); /*!< in: mtr */ -/********************************************************************//** -*/ -void -rtr_get_father_node( -/*================*/ - dict_index_t* index, /*!< in: index */ - ulint level, /*!< in: the tree level of search */ - const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in - tuple must be set so that it cannot get - compared to the node ptr page number field! */ - btr_cur_t* sea_cur,/*!< in: search cursor */ - btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is - s- or x-latched */ - ulint page_no,/*!< in: current page no */ - mtr_t* mtr); /*!< in: mtr */ - /**************************************************************//** push a nonleaf index node to the search path */ UNIV_INLINE From 5a1d93152996952b7c26869ae1caa4262893dfce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Apr 2020 19:05:56 +0300 Subject: [PATCH 32/35] Speed up innodb_gis.rtree_split INSERT...SELECT reading from an InnoDB table is slow due to creating explicit record locks. Use the sequence engine instead. Also, remove the space before rtr_page_need_second_split to actually make the debug injection work. --- .../suite/innodb_gis/r/rtree_split.result | 56 ++++------------ .../suite/innodb_gis/t/rtree_split.test | 64 +++++-------------- 2 files changed, 30 insertions(+), 90 deletions(-) diff --git a/mysql-test/suite/innodb_gis/r/rtree_split.result b/mysql-test/suite/innodb_gis/r/rtree_split.result index 518319ff3d6..df88960ba3d 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_split.result +++ b/mysql-test/suite/innodb_gis/r/rtree_split.result @@ -1,52 +1,24 @@ create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb; -insert into t1 values(1, Point(1,1)); -insert into t1 values(2, Point(2,2)); -insert into t1 values(3, Point(3,3)); -insert into t1 values(4, Point(4,4)); -insert into t1 values(5, Point(5,5)); -insert into t1 values(6, Point(6,6)); -insert into t1 values(7, Point(7,7)); -insert into t1 values(8, Point(8,8)); -insert into t1 values(9, Point(9,9)); -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; +begin; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_576; SET @saved_dbug = @@SESSION.debug_dbug; -SET debug_dbug = '+d, rtr_page_need_second_split'; -insert into t1 select * from t1; +SET debug_dbug = '+d,rtr_page_need_second_split'; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_576; SET debug_dbug = @saved_dbug; -delete from t1; -insert into t1 values(1, Point(1,1)); -insert into t1 values(2, Point(2,2)); -insert into t1 values(3, Point(3,3)); -insert into t1 values(4, Point(4,4)); -insert into t1 values(5, Point(5,5)); -insert into t1 values(6, Point(6,6)); -insert into t1 values(7, Point(7,7)); -insert into t1 values(8, Point(8,8)); -insert into t1 values(9, Point(9,9)); -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -start transaction; -insert into t1 select * from t1; +rollback; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_2304; +begin; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_2304; rollback; check table t1; Table Op Msg_type Msg_text test.t1 check status OK -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_71424; check table t1; Table Op Msg_type Msg_text test.t1 check status OK diff --git a/mysql-test/suite/innodb_gis/t/rtree_split.test b/mysql-test/suite/innodb_gis/t/rtree_split.test index caf79becbd0..af626dba6b7 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_split.test +++ b/mysql-test/suite/innodb_gis/t/rtree_split.test @@ -1,5 +1,5 @@ # WL#6745 InnoDB R-tree support -# This test case will test R-tree split, mostly on duplciate records. +# This test case will test R-tree split, mostly on duplicate records. # Not supported in embedded --source include/not_embedded.inc @@ -8,65 +8,33 @@ --source include/big_test.inc --source include/not_valgrind.inc --source include/have_debug.inc +--source include/have_sequence.inc # Create table with R-tree index. create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb; +begin; # Insert enough values to let R-tree split. -insert into t1 values(1, Point(1,1)); -insert into t1 values(2, Point(2,2)); -insert into t1 values(3, Point(3,3)); -insert into t1 values(4, Point(4,4)); -insert into t1 values(5, Point(5,5)); -insert into t1 values(6, Point(6,6)); -insert into t1 values(7, Point(7,7)); -insert into t1 values(8, Point(8,8)); -insert into t1 values(9, Point(9,9)); - -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_576; #Check second round spliting. SET @saved_dbug = @@SESSION.debug_dbug; -SET debug_dbug = '+d, rtr_page_need_second_split'; -insert into t1 select * from t1; +SET debug_dbug = '+d,rtr_page_need_second_split'; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_576; SET debug_dbug = @saved_dbug; +rollback; -delete from t1; - -insert into t1 values(1, Point(1,1)); -insert into t1 values(2, Point(2,2)); -insert into t1 values(3, Point(3,3)); -insert into t1 values(4, Point(4,4)); -insert into t1 values(5, Point(5,5)); -insert into t1 values(6, Point(6,6)); -insert into t1 values(7, Point(7,7)); -insert into t1 values(8, Point(8,8)); -insert into t1 values(9, Point(9,9)); - -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; - -insert into t1 select * from t1; -insert into t1 select * from t1; - -insert into t1 select * from t1; -insert into t1 select * from t1; -start transaction; -insert into t1 select * from t1; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_2304; +begin; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_2304; rollback; check table t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_71424; check table t1; select count(*) from t1; From 2644e52fdbb7943a549f467b4dfd97da2592039d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Apr 2020 08:42:45 +0300 Subject: [PATCH 33/35] MDEV-22384 Wrong estimate of affected BLOB columns in update of PRIMARY KEY During the UPDATE of PRIMARY KEY columns, we may miscalculate the size of the clustered index record. row_upd_clust_rec_by_insert(): Pass the total number of off-page columns, which may include such columns that were inherited from the record and not created as part of the UPDATE operation. This is based on mysql/mysql-server@490c45e8c8e07197958dbb21214fd45ed668b559 which is a follow-up to mysql/mysql-server@1fa475b85d24de4b9ce2958c0eed738c221fc82c which we filed and fixed as MDEV-21511. No test case was provided by Oracle. --- storage/innobase/row/row0upd.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 31d4d31c1f9..3cd2a1ef04f 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2805,8 +2805,7 @@ check_fk: mtr_commit(mtr); err = row_ins_clust_index_entry( - index, entry, thr, - node->upd_ext ? node->upd_ext->n_ext : 0); + index, entry, thr, dtuple_get_n_ext(entry)); node->state = UPD_NODE_INSERT_CLUSTERED; mem_heap_free(heap); From cfbbf5424bc68a31a996ab42a253f2c96365599c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 29 Apr 2020 11:50:03 +0300 Subject: [PATCH 34/35] MDEV-7962: Follow-up fix for 10.4 Replace wsrep_on() with trx_t::is_wsrep() where possible. Also, rename some functions to member functions and remove unused DBUG_EXECUTE_IF instrumentation: trx_t::commit(): Renamed from trx_commit(). trx_t::commit_low(): Renamed from trx_commit_low(). trx_t::commit_in_memory(): Renamed from trx_commit_in_memory(). --- storage/innobase/handler/handler0alter.cc | 4 +- storage/innobase/include/trx0trx.h | 36 +- storage/innobase/lock/lock0lock.cc | 5 +- storage/innobase/trx/trx0roll.cc | 4 +- storage/innobase/trx/trx0trx.cc | 464 ++++++++++------------ 5 files changed, 222 insertions(+), 291 deletions(-) diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index fc270c496f2..64607293ed9 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -7079,7 +7079,7 @@ op_ok: goto error_handling; } - trx_commit(ctx->trx); + ctx->trx->commit(); trx_start_for_ddl(ctx->trx, op); if (!ctx->new_table->fts @@ -11101,7 +11101,7 @@ ha_innobase::commit_inplace_alter_table( logical sense the commit in the file-based data structures happens here. */ - trx_commit_low(trx, &mtr); + trx->commit_low(&mtr); } /* If server crashes here, the dictionary in diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 6911f2ec084..3856915f8a6 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -181,17 +181,6 @@ trx_start_for_ddl_low( trx_start_for_ddl_low((t), (o)) #endif /* UNIV_DEBUG */ -/****************************************************************//** -Commits a transaction. */ -void -trx_commit( -/*=======*/ - trx_t* trx); /*!< in/out: transaction */ - -/** Commit a transaction and a mini-transaction. -@param[in,out] trx transaction -@param[in,out] mtr mini-transaction (NULL if no modifications) */ -void trx_commit_low(trx_t* trx, mtr_t* mtr); /**********************************************************************//** Does the transaction commit for MySQL. @return DB_SUCCESS or error number */ @@ -898,10 +887,10 @@ public: defer flush of the logs to disk until after we release the mutex. */ - bool must_flush_log_later;/*!< this flag is set to TRUE in - trx_commit() if flush_log_later was - TRUE, and there were modifications by - the transaction; in that case we must + bool must_flush_log_later;/*!< set in commit() + if flush_log_later was + set and redo log was written; + in that case we will flush the log in trx_commit_complete_for_mysql() */ ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */ @@ -1132,11 +1121,20 @@ public: @param[in] table_id table identifier */ void evict_table(table_id_t table_id); +private: + /** Mark a transaction committed in the main memory data structures. */ + inline void commit_in_memory(const mtr_t *mtr); +public: + /** Commit the transaction. */ + void commit(); - bool is_referenced() - { - return n_ref > 0; - } + /** Commit the transaction in a mini-transaction. + @param mtr mini-transaction (if there are any persistent modifications) */ + void commit_low(mtr_t *mtr= nullptr); + + + + bool is_referenced() const { return n_ref > 0; } void reference() diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index d0b553168b2..6604ff3599a 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -6865,7 +6865,7 @@ DeadlockChecker::trx_rollback() print("*** WE ROLL BACK TRANSACTION (1)\n"); #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && wsrep_thd_is_SR(trx->mysql_thd)) { + if (trx->is_wsrep() && wsrep_thd_is_SR(trx->mysql_thd)) { wsrep_handle_SR_rollback(m_start->mysql_thd, trx->mysql_thd); } #endif @@ -6956,8 +6956,7 @@ DeadlockChecker::check_and_resolve(const lock_t* lock, trx_t* trx) print("*** WE ROLL BACK TRANSACTION (2)\n"); #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) - && wsrep_thd_is_SR(trx->mysql_thd)) { + if (trx->is_wsrep() && wsrep_thd_is_SR(trx->mysql_thd)) { wsrep_handle_SR_rollback(trx->mysql_thd, victim_trx->mysql_thd); } diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index fbc9d746f57..c25e2e56111 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -59,7 +59,7 @@ static bool trx_rollback_finish(trx_t* trx) trx->mod_tables.clear(); bool finished = trx->error_state == DB_SUCCESS; if (UNIV_LIKELY(finished)) { - trx_commit(trx); + trx->commit(); } else { ut_a(trx->error_state == DB_INTERRUPTED); ut_ad(!srv_is_being_started); @@ -84,7 +84,7 @@ static bool trx_rollback_finish(trx_t* trx) ut_free(undo); undo = NULL; } - trx_commit_low(trx, NULL); + trx->commit_low(); } trx->lock.que_state = TRX_QUE_RUNNING; diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 082a553c4a6..7c25d5b61c2 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1338,316 +1338,255 @@ void trx_t::evict_table(table_id_t table_id) } } -/****************************************************************//** -Commits a transaction in memory. */ -static -void -trx_commit_in_memory( -/*=================*/ - trx_t* trx, /*!< in/out: transaction */ - const mtr_t* mtr) /*!< in: mini-transaction of - trx_write_serialisation_history(), or NULL if - the transaction did not modify anything */ +/** Mark a transaction committed in the main memory data structures. */ +inline void trx_t::commit_in_memory(const mtr_t *mtr) { - trx->must_flush_log_later = false; - trx->read_view.close(); + must_flush_log_later= false; + read_view.close(); - if (trx_is_autocommit_non_locking(trx)) { - ut_ad(trx->id == 0); - ut_ad(trx->read_only); - ut_a(!trx->is_recovered); - ut_ad(trx->rsegs.m_redo.rseg == NULL); + if (trx_is_autocommit_non_locking(this)) + { + ut_ad(id == 0); + ut_ad(read_only); + ut_a(!is_recovered); + ut_ad(!rsegs.m_redo.rseg); - /* Note: We are asserting without holding the lock mutex. But - that is OK because this transaction is not waiting and cannot - be rolled back and no new locks can (or should) be added - because it is flagged as a non-locking read-only transaction. */ + /* Note: We are asserting without holding the lock mutex. But + that is OK because this transaction is not waiting and cannot + be rolled back and no new locks can (or should) be added + because it is flagged as a non-locking read-only transaction. */ + ut_a(UT_LIST_GET_LEN(lock.trx_locks) == 0); - ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0); + /* This state change is not protected by any mutex, therefore + there is an inherent race here around state transition during + printouts. We ignore this race for the sake of efficiency. + However, the trx_sys_t::mutex will protect the trx_t instance + and it cannot be removed from the trx_list and freed + without first acquiring the trx_sys_t::mutex. */ + ut_ad(trx_state_eq(this, TRX_STATE_ACTIVE)); - /* This state change is not protected by any mutex, therefore - there is an inherent race here around state transition during - printouts. We ignore this race for the sake of efficiency. - However, the trx_sys_t::mutex will protect the trx_t instance - and it cannot be removed from the trx_list and freed - without first acquiring the trx_sys_t::mutex. */ + MONITOR_INC(MONITOR_TRX_NL_RO_COMMIT); - ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); - - MONITOR_INC(MONITOR_TRX_NL_RO_COMMIT); - - DBUG_LOG("trx", "Autocommit in memory: " << trx); - trx->state = TRX_STATE_NOT_STARTED; - } else { + DBUG_LOG("trx", "Autocommit in memory: " << this); + state= TRX_STATE_NOT_STARTED; + } + else + { #ifdef UNIV_DEBUG - if (!UT_LIST_GET_LEN(trx->lock.trx_locks)) { - for (lock_list::iterator it - = trx->lock.table_locks.begin(); - it != trx->lock.table_locks.end(); - it++) { - ut_ad(!*it); - } - } + if (!UT_LIST_GET_LEN(lock.trx_locks)) + for (auto l : lock.table_locks) + ut_ad(!l); #endif /* UNIV_DEBUG */ - trx->commit_state(); + commit_state(); - if (trx->id) { - trx_sys.deregister_rw(trx); + if (id) + { + trx_sys.deregister_rw(this); - /* Wait for any implicit-to-explicit lock - conversions to cease, so that there will be no - race condition in lock_release(). */ - while (UNIV_UNLIKELY(trx->is_referenced())) { - ut_delay(srv_spin_wait_delay); - } + /* Wait for any implicit-to-explicit lock conversions to cease, + so that there will be no race condition in lock_release(). */ + while (UNIV_UNLIKELY(is_referenced())) + ut_delay(srv_spin_wait_delay); + release_locks(); + id= 0; + } + else + { + ut_ad(read_only || !rsegs.m_redo.rseg); + release_locks(); + } - trx->release_locks(); - trx->id = 0; - } else { - ut_ad(trx->read_only || !trx->rsegs.m_redo.rseg); - trx->release_locks(); - } + DEBUG_SYNC_C("after_trx_committed_in_memory"); - DEBUG_SYNC_C("after_trx_committed_in_memory"); + if (read_only || !rsegs.m_redo.rseg) + { + MONITOR_INC(MONITOR_TRX_RO_COMMIT); + } + else + { + trx_update_mod_tables_timestamp(this); + MONITOR_INC(MONITOR_TRX_RW_COMMIT); + is_recovered= false; + } - if (trx->read_only || !trx->rsegs.m_redo.rseg) { - MONITOR_INC(MONITOR_TRX_RO_COMMIT); - } else { - trx_update_mod_tables_timestamp(trx); - MONITOR_INC(MONITOR_TRX_RW_COMMIT); - trx->is_recovered = false; - } + while (dict_table_t *table= UT_LIST_GET_FIRST(lock.evicted_tables)) + { + UT_LIST_REMOVE(lock.evicted_tables, table); + dict_mem_table_free(table); + } + } - while (dict_table_t* table = UT_LIST_GET_FIRST( - trx->lock.evicted_tables)) { - UT_LIST_REMOVE(trx->lock.evicted_tables, table); - dict_mem_table_free(table); - } - } + ut_ad(!rsegs.m_redo.undo); + ut_ad(UT_LIST_GET_LEN(lock.evicted_tables) == 0); - ut_ad(!trx->rsegs.m_redo.undo); - ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0); + if (trx_rseg_t *rseg= rsegs.m_redo.rseg) + { + mutex_enter(&rseg->mutex); + ut_ad(rseg->trx_ref_count > 0); + --rseg->trx_ref_count; + mutex_exit(&rseg->mutex); - if (trx_rseg_t* rseg = trx->rsegs.m_redo.rseg) { - mutex_enter(&rseg->mutex); - ut_ad(rseg->trx_ref_count > 0); - --rseg->trx_ref_count; - mutex_exit(&rseg->mutex); + if (trx_undo_t *&insert= rsegs.m_redo.old_insert) + { + ut_ad(insert->rseg == rseg); + trx_undo_commit_cleanup(insert, false); + insert= nullptr; + } + } - if (trx_undo_t*& insert = trx->rsegs.m_redo.old_insert) { - ut_ad(insert->rseg == rseg); - trx_undo_commit_cleanup(insert, false); - insert = NULL; - } - } + ut_ad(!rsegs.m_redo.old_insert); - ut_ad(!trx->rsegs.m_redo.old_insert); + if (mtr) + { + if (trx_undo_t *&undo= rsegs.m_noredo.undo) + { + ut_ad(undo->rseg == rsegs.m_noredo.rseg); + trx_undo_commit_cleanup(undo, true); + undo= nullptr; + } - if (mtr != NULL) { - if (trx_undo_t*& undo = trx->rsegs.m_noredo.undo) { - ut_ad(undo->rseg == trx->rsegs.m_noredo.rseg); - trx_undo_commit_cleanup(undo, true); - undo = NULL; - } + /* NOTE that we could possibly make a group commit more efficient + here: call os_thread_yield here to allow also other trxs to come + to commit! */ - /* NOTE that we could possibly make a group commit more - efficient here: call os_thread_yield here to allow also other - trxs to come to commit! */ + /*-------------------------------------*/ - /*-------------------------------------*/ + /* Depending on the my.cnf options, we may now write the log + buffer to the log files, making the transaction durable if the OS + does not crash. We may also flush the log files to disk, making + the transaction durable also at an OS crash or a power outage. - /* Depending on the my.cnf options, we may now write the log - buffer to the log files, making the transaction durable if - the OS does not crash. We may also flush the log files to - disk, making the transaction durable also at an OS crash or a - power outage. + The idea in InnoDB's group commit is that a group of transactions + gather behind a trx doing a physical disk write to log files, and + when that physical write has been completed, one of those + transactions does a write which commits the whole group. Note that + this group commit will only bring benefit if there are > 2 users + in the database. Then at least 2 users can gather behind one doing + the physical log write to disk. - The idea in InnoDB's group commit is that a group of - transactions gather behind a trx doing a physical disk write - to log files, and when that physical write has been completed, - one of those transactions does a write which commits the whole - group. Note that this group commit will only bring benefit if - there are > 2 users in the database. Then at least 2 users can - gather behind one doing the physical log write to disk. + If we are calling trx_t::commit() under prepare_commit_mutex, we + will delay possible log write and flush to a separate function + trx_commit_complete_for_mysql(), which is only called when the + thread has released the mutex. This is to make the group commit + algorithm to work. Otherwise, the prepare_commit mutex would + serialize all commits and prevent a group of transactions from + gathering. */ - If we are calling trx_commit() under prepare_commit_mutex, we - will delay possible log write and flush to a separate function - trx_commit_complete_for_mysql(), which is only called when the - thread has released the mutex. This is to make the - group commit algorithm to work. Otherwise, the prepare_commit - mutex would serialize all commits and prevent a group of - transactions from gathering. */ + commit_lsn= mtr->commit_lsn(); + if (!commit_lsn) + /* Nothing to be done. */; + else if (flush_log_later) + /* Do nothing yet */ + must_flush_log_later= true; + else if (srv_flush_log_at_trx_commit) + trx_flush_log_if_needed(commit_lsn, this); - lsn_t lsn = mtr->commit_lsn(); + /* Tell server some activity has happened, since the trx does + changes something. Background utility threads like master thread, + purge thread or page_cleaner thread might have some work to do. */ + srv_active_wake_master_thread(); + } - if (lsn == 0) { - /* Nothing to be done. */ - } else if (trx->flush_log_later) { - /* Do nothing yet */ - trx->must_flush_log_later = true; - } else if (srv_flush_log_at_trx_commit == 0) { - /* Do nothing */ - } else { - trx_flush_log_if_needed(lsn, trx); - } + ut_ad(!rsegs.m_noredo.undo); - trx->commit_lsn = lsn; + /* Free all savepoints, starting from the first. */ + trx_named_savept_t *savep= UT_LIST_GET_FIRST(trx_savepoints); - /* Tell server some activity has happened, since the trx - does changes something. Background utility threads like - master thread, purge thread or page_cleaner thread might - have some work to do. */ - srv_active_wake_master_thread(); - } + trx_roll_savepoints_free(this, savep); - ut_ad(!trx->rsegs.m_noredo.undo); + if (fts_trx) + trx_finalize_for_fts(this, undo_no != 0); - /* Free all savepoints, starting from the first. */ - trx_named_savept_t* savep = UT_LIST_GET_FIRST(trx->trx_savepoints); + trx_mutex_enter(this); + dict_operation= TRX_DICT_OP_NONE; + lock.was_chosen_as_deadlock_victim= false; - trx_roll_savepoints_free(trx, savep); + DBUG_LOG("trx", "Commit in memory: " << this); + state= TRX_STATE_NOT_STARTED; - if (trx->fts_trx != NULL) { - trx_finalize_for_fts(trx, trx->undo_no != 0); - } + assert_trx_is_free(this); + trx_init(this); + trx_mutex_exit(this); - trx_mutex_enter(trx); - trx->dict_operation = TRX_DICT_OP_NONE; - trx->lock.was_chosen_as_deadlock_victim = false; - - DBUG_LOG("trx", "Commit in memory: " << trx); - trx->state = TRX_STATE_NOT_STARTED; - - assert_trx_is_free(trx); - - trx_init(trx); - - trx_mutex_exit(trx); - - ut_a(trx->error_state == DB_SUCCESS); - if (!srv_read_only_mode) { - srv_wake_purge_thread_if_not_active(); - } + ut_a(error_state == DB_SUCCESS); + if (!srv_read_only_mode) + srv_wake_purge_thread_if_not_active(); } -/** Commit a transaction and a mini-transaction. -@param[in,out] trx transaction -@param[in,out] mtr mini-transaction (NULL if no modifications) */ -void trx_commit_low(trx_t* trx, mtr_t* mtr) +/** Commit the transaction in a mini-transaction. +@param mtr mini-transaction (if there are any persistent modifications) */ +void trx_t::commit_low(mtr_t *mtr) { - assert_trx_nonlocking_or_in_list(trx); - ut_ad(!trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY)); - ut_ad(!mtr || mtr->is_active()); - ut_d(bool aborted = trx->in_rollback - && trx->error_state == DB_DEADLOCK); - ut_ad(!mtr == (aborted || !trx->has_logged_or_recovered())); - ut_ad(!mtr || !aborted); + assert_trx_nonlocking_or_in_list(this); + ut_ad(!trx_state_eq(this, TRX_STATE_COMMITTED_IN_MEMORY)); + ut_ad(!mtr || mtr->is_active()); + ut_d(bool aborted = in_rollback && error_state == DB_DEADLOCK); + ut_ad(!mtr == (aborted || !has_logged_or_recovered())); + ut_ad(!mtr || !aborted); - /* undo_no is non-zero if we're doing the final commit. */ - if (trx->fts_trx != NULL && trx->undo_no != 0) { - dberr_t error; - - ut_a(!trx_is_autocommit_non_locking(trx)); - - error = fts_commit(trx); - - /* FTS-FIXME: Temporarily tolerate DB_DUPLICATE_KEY - instead of dying. This is a possible scenario if there - is a crash between insert to DELETED table committing - and transaction committing. The fix would be able to - return error from this function */ - if (error != DB_SUCCESS && error != DB_DUPLICATE_KEY) { - /* FTS-FIXME: once we can return values from this - function, we should do so and signal an error - instead of just dying. */ - - ut_error; - } - } + /* undo_no is non-zero if we're doing the final commit. */ + if (fts_trx && undo_no) + { + ut_a(!trx_is_autocommit_non_locking(this)); + dberr_t error= fts_commit(this); + /* FTS-FIXME: Temporarily tolerate DB_DUPLICATE_KEY instead of + dying. This is a possible scenario if there is a crash between + insert to DELETED table committing and transaction committing. The + fix would be able to return error from this function */ + ut_a(error == DB_SUCCESS || error == DB_DUPLICATE_KEY); + } #ifndef DBUG_OFF - const bool debug_sync = trx->mysql_thd && trx->has_logged_persistent(); + const bool debug_sync= mysql_thd && has_logged_persistent(); #endif - if (mtr != NULL) { - trx_write_serialisation_history(trx, mtr); + if (mtr) + { + trx_write_serialisation_history(this, mtr); - /* The following call commits the mini-transaction, making the - whole transaction committed in the file-based world, at this - log sequence number. The transaction becomes 'durable' when - we write the log to disk, but in the logical sense the commit - in the file-based data structures (undo logs etc.) happens - here. + /* The following call commits the mini-transaction, making the + whole transaction committed in the file-based world, at this log + sequence number. The transaction becomes 'durable' when we write + the log to disk, but in the logical sense the commit in the + file-based data structures (undo logs etc.) happens here. - NOTE that transaction numbers, which are assigned only to - transactions with an update undo log, do not necessarily come - in exactly the same order as commit lsn's, if the transactions - have different rollback segments. To get exactly the same - order we should hold the kernel mutex up to this point, - adding to the contention of the kernel mutex. However, if - a transaction T2 is able to see modifications made by - a transaction T1, T2 will always get a bigger transaction - number and a bigger commit lsn than T1. */ + NOTE that transaction numbers, which are assigned only to + transactions with an update undo log, do not necessarily come in + exactly the same order as commit lsn's, if the transactions have + different rollback segments. To get exactly the same order we + should hold the kernel mutex up to this point, adding to the + contention of the kernel mutex. However, if a transaction T2 is + able to see modifications made by a transaction T1, T2 will always + get a bigger transaction number and a bigger commit lsn than T1. */ - /*--------------*/ - mtr_commit(mtr); - - DBUG_EXECUTE_IF("ib_crash_during_trx_commit_in_mem", - if (trx->has_logged()) { - log_write_up_to(mtr->commit_lsn(), - true); - DBUG_SUICIDE(); - }); - /*--------------*/ - } + mtr->commit(); + } #ifndef DBUG_OFF - /* In case of this function is called from a stack executing - THD::release_resources -> ... - innobase_connection_close() -> - trx_rollback_for_mysql... -> . - mysql's thd does not seem to have - thd->debug_sync_control defined any longer. However the stack - is possible only with a prepared trx not updating any data. - */ - if (debug_sync) { - DEBUG_SYNC_C("before_trx_state_committed_in_memory"); - } + if (debug_sync) + DEBUG_SYNC_C("before_trx_state_committed_in_memory"); #endif - trx_commit_in_memory(trx, mtr); + commit_in_memory(mtr); } -/****************************************************************//** -Commits a transaction. */ -void -trx_commit( -/*=======*/ - trx_t* trx) /*!< in/out: transaction */ + +void trx_t::commit() { - mtr_t* mtr; - mtr_t local_mtr; + mtr_t *mtr= nullptr; + mtr_t local_mtr; - DBUG_EXECUTE_IF("ib_trx_commit_crash_before_trx_commit_start", - DBUG_SUICIDE();); - - if (trx->has_logged_or_recovered()) { - mtr = &local_mtr; - mtr->start(); - } else { - - mtr = NULL; - } - - trx_commit_low(trx, mtr); + if (has_logged_or_recovered()) + { + mtr= &local_mtr; + local_mtr.start(); + } + commit_low(mtr); #ifdef WITH_WSREP - /* Serialization history has been written and the - transaction is committed in memory, which makes - this commit ordered. Release commit order critical - section. */ - if (wsrep_on(trx->mysql_thd)) - { - wsrep_commit_ordered(trx->mysql_thd); - } + /* Serialization history has been written and the transaction is + committed in memory, which makes this commit ordered. Release commit + order critical section. */ + if (mtr && is_wsrep()) + wsrep_commit_ordered(mysql_thd); #endif /* WITH_WSREP */ } @@ -1741,11 +1680,8 @@ trx_commit_step( trx_commit_or_rollback_prepare(trx); trx->lock.que_state = TRX_QUE_COMMITTING; - - trx_commit(trx); - + trx->commit(); ut_ad(trx->lock.wait_thr == NULL); - trx->lock.que_state = TRX_QUE_RUNNING; thr = NULL; @@ -1783,9 +1719,7 @@ trx_commit_for_mysql( case TRX_STATE_PREPARED: case TRX_STATE_PREPARED_RECOVERED: trx->op_info = "committing"; - - trx_commit(trx); - + trx->commit(); MONITOR_DEC(MONITOR_TRX_ACTIVE); trx->op_info = ""; return(DB_SUCCESS); From 5ba2aa1ddc074dc89db7f265ddb61ce96f714fc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 29 Apr 2020 14:54:36 +0300 Subject: [PATCH 35/35] MDEV-7962: Remove one more wsrep_on() trx_rollback_to_savepoint(): Invoke trx_t::is_wsrep(). --- storage/innobase/trx/trx0roll.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index c25e2e56111..75bffd91aa7 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -178,8 +178,7 @@ trx_rollback_to_savepoint( complete rollback */ { #ifdef WITH_WSREP - if (savept == NULL && wsrep_on(trx->mysql_thd) - && wsrep_thd_is_SR(trx->mysql_thd)) { + if (!savept && trx->is_wsrep() && wsrep_thd_is_SR(trx->mysql_thd)) { wsrep_handle_SR_rollback(NULL, trx->mysql_thd); } #endif /* WITH_WSREP */