From 4d9977e5ff9843e132fda480536192caaf69aba2 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Sat, 21 Mar 2020 15:52:24 +0400 Subject: [PATCH 1/7] default_gtid_pos_table: my_atomic to std::atomic --- client/mysqlbinlog.cc | 1 + sql/rpl_gtid.cc | 14 +++++--------- sql/rpl_gtid.h | 2 +- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index c12f51457ea..a291d82a134 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -41,6 +41,7 @@ /* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */ #include "sql_priv.h" #include "sql_basic_types.h" +#include #include "log_event.h" #include "compat56.h" #include "sql_common.h" diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 5681f8652a4..8f9fdcaffde 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -497,7 +497,7 @@ gtid_check_rpl_slave_state_table(TABLE *table) void rpl_slave_state::select_gtid_pos_table(THD *thd, LEX_CSTRING *out_tablename) { - struct gtid_pos_table *list, *table_entry, *default_entry; + struct gtid_pos_table *list, *table_entry; /* See comments on rpl_slave_state::gtid_pos_tables for rules around proper @@ -565,9 +565,8 @@ rpl_slave_state::select_gtid_pos_table(THD *thd, LEX_CSTRING *out_tablename) already active in the transaction, or if there is no current transaction engines available, we return the default gtid_slave_pos table. */ - default_entry= (struct gtid_pos_table *) - my_atomic_loadptr_explicit(&default_gtid_pos_table, MY_MEMORY_ORDER_ACQUIRE); - *out_tablename= default_entry->table_name; + *out_tablename= + default_gtid_pos_table.load(std::memory_order_acquire)->table_name; /* Record in status that we failed to find a suitable gtid_pos table. */ if (count > 0) { @@ -840,9 +839,7 @@ rpl_slave_state::select_gtid_pos_table(void *hton) table_entry= table_entry->next; } - table_entry= (struct gtid_pos_table *) - my_atomic_loadptr_explicit(&default_gtid_pos_table, MY_MEMORY_ORDER_ACQUIRE); - return &table_entry->table_name; + return &default_gtid_pos_table.load(std::memory_order_acquire)->table_name; } @@ -1445,8 +1442,7 @@ rpl_slave_state::set_gtid_pos_tables_list(rpl_slave_state::gtid_pos_table *new_l mysql_mutex_assert_owner(&LOCK_slave_state); old_list= (struct gtid_pos_table *)gtid_pos_tables; my_atomic_storeptr_explicit(>id_pos_tables, new_list, MY_MEMORY_ORDER_RELEASE); - my_atomic_storeptr_explicit(&default_gtid_pos_table, default_entry, - MY_MEMORY_ORDER_RELEASE); + default_gtid_pos_table.store(default_entry, std::memory_order_release); free_gtid_pos_tables(old_list); } diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h index 167d7461a7e..a795290d780 100644 --- a/sql/rpl_gtid.h +++ b/sql/rpl_gtid.h @@ -223,7 +223,7 @@ struct rpl_slave_state */ void * volatile gtid_pos_tables; /* The default entry in gtid_pos_tables, mysql.gtid_slave_pos. */ - void * volatile default_gtid_pos_table; + std::atomic default_gtid_pos_table; bool loaded; rpl_slave_state(); From a39d92ca574e275acaf4240629d4bee5f9ece3f6 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Sat, 21 Mar 2020 17:36:38 +0400 Subject: [PATCH 2/7] gtid_pos_table: my_atomic to std::atomic --- sql/rpl_gtid.cc | 24 ++++++++---------------- sql/rpl_gtid.h | 5 +---- sql/rpl_rli.cc | 11 +++++------ sql/slave.cc | 8 ++++---- 4 files changed, 18 insertions(+), 30 deletions(-) diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 8f9fdcaffde..f58df09623c 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -257,7 +257,7 @@ rpl_slave_state::rpl_slave_state() rpl_slave_state::~rpl_slave_state() { - free_gtid_pos_tables((struct gtid_pos_table *)gtid_pos_tables); + free_gtid_pos_tables(gtid_pos_tables.load(std::memory_order_relaxed)); truncate_hash(); my_hash_free(&hash); delete_dynamic(>id_sort_array); @@ -497,21 +497,18 @@ gtid_check_rpl_slave_state_table(TABLE *table) void rpl_slave_state::select_gtid_pos_table(THD *thd, LEX_CSTRING *out_tablename) { - struct gtid_pos_table *list, *table_entry; - /* See comments on rpl_slave_state::gtid_pos_tables for rules around proper access to the list. */ - list= (struct gtid_pos_table *) - my_atomic_loadptr_explicit(>id_pos_tables, MY_MEMORY_ORDER_ACQUIRE); + auto list= gtid_pos_tables.load(std::memory_order_acquire); Ha_trx_info *ha_info; uint count = 0; for (ha_info= thd->transaction.all.ha_list; ha_info; ha_info= ha_info->next()) { void *trx_hton= ha_info->ht(); - table_entry= list; + auto table_entry= list; if (!ha_info->is_trx_read_write() || trx_hton == binlog_hton) continue; @@ -820,14 +817,11 @@ rpl_slave_state::gtid_grab_pending_delete_list() LEX_CSTRING * rpl_slave_state::select_gtid_pos_table(void *hton) { - struct gtid_pos_table *table_entry; - /* See comments on rpl_slave_state::gtid_pos_tables for rules around proper access to the list. */ - table_entry= (struct gtid_pos_table *) - my_atomic_loadptr_explicit(>id_pos_tables, MY_MEMORY_ORDER_ACQUIRE); + auto table_entry= gtid_pos_tables.load(std::memory_order_acquire); while (table_entry) { @@ -1437,11 +1431,9 @@ void rpl_slave_state::set_gtid_pos_tables_list(rpl_slave_state::gtid_pos_table *new_list, rpl_slave_state::gtid_pos_table *default_entry) { - gtid_pos_table *old_list; - mysql_mutex_assert_owner(&LOCK_slave_state); - old_list= (struct gtid_pos_table *)gtid_pos_tables; - my_atomic_storeptr_explicit(>id_pos_tables, new_list, MY_MEMORY_ORDER_RELEASE); + auto old_list= gtid_pos_tables.load(std::memory_order_relaxed); + gtid_pos_tables.store(new_list, std::memory_order_release); default_gtid_pos_table.store(default_entry, std::memory_order_release); free_gtid_pos_tables(old_list); } @@ -1451,8 +1443,8 @@ void rpl_slave_state::add_gtid_pos_table(rpl_slave_state::gtid_pos_table *entry) { mysql_mutex_assert_owner(&LOCK_slave_state); - entry->next= (struct gtid_pos_table *)gtid_pos_tables; - my_atomic_storeptr_explicit(>id_pos_tables, entry, MY_MEMORY_ORDER_RELEASE); + entry->next= gtid_pos_tables.load(std::memory_order_relaxed); + gtid_pos_tables.store(entry, std::memory_order_release); } diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h index a795290d780..b633716bfe5 100644 --- a/sql/rpl_gtid.h +++ b/sql/rpl_gtid.h @@ -217,11 +217,8 @@ struct rpl_slave_state The list can be read without lock by an SQL driver thread or worker thread by reading the gtid_pos_tables pointer atomically with acquire semantics, to ensure that it will see the correct next pointer of a new head element. - - The type is struct gtid_pos_table *, but needs to be void * to allow using - my_atomic operations without violating C strict aliasing semantics. */ - void * volatile gtid_pos_tables; + std::atomic gtid_pos_tables; /* The default entry in gtid_pos_tables, mysql.gtid_slave_pos. */ std::atomic default_gtid_pos_table; bool loaded; diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index d645fea6968..18ee6a98ed0 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -2019,10 +2019,9 @@ find_gtid_slave_pos_tables(THD *thd) However we can add new entries, and warn about any tables that disappeared, but may still be visible to running SQL threads. */ - rpl_slave_state::gtid_pos_table *old_entry, *new_entry, **next_ptr_ptr; - - old_entry= (rpl_slave_state::gtid_pos_table *) - rpl_global_gtid_slave_state->gtid_pos_tables; + rpl_slave_state::gtid_pos_table *new_entry, **next_ptr_ptr; + auto old_entry= rpl_global_gtid_slave_state-> + gtid_pos_tables.load(std::memory_order_relaxed); while (old_entry) { new_entry= cb_data.table_list; @@ -2044,8 +2043,8 @@ find_gtid_slave_pos_tables(THD *thd) while (new_entry) { /* Check if we already have a table with this storage engine. */ - old_entry= (rpl_slave_state::gtid_pos_table *) - rpl_global_gtid_slave_state->gtid_pos_tables; + old_entry= rpl_global_gtid_slave_state-> + gtid_pos_tables.load(std::memory_order_relaxed); while (old_entry) { if (new_entry->table_hton == old_entry->table_hton) diff --git a/sql/slave.cc b/sql/slave.cc index 714e47424fe..fcb4777b189 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -397,8 +397,8 @@ handle_gtid_pos_auto_create_request(THD *thd, void *hton) /* Find the entry for the table to auto-create. */ mysql_mutex_lock(&rpl_global_gtid_slave_state->LOCK_slave_state); - entry= (rpl_slave_state::gtid_pos_table *) - rpl_global_gtid_slave_state->gtid_pos_tables; + entry= rpl_global_gtid_slave_state-> + gtid_pos_tables.load(std::memory_order_relaxed); while (entry) { if (entry->table_hton == hton && @@ -434,8 +434,8 @@ handle_gtid_pos_auto_create_request(THD *thd, void *hton) /* Now enable the entry for the auto-created table. */ mysql_mutex_lock(&rpl_global_gtid_slave_state->LOCK_slave_state); - entry= (rpl_slave_state::gtid_pos_table *) - rpl_global_gtid_slave_state->gtid_pos_tables; + entry= rpl_global_gtid_slave_state-> + gtid_pos_tables.load(std::memory_order_relaxed); while (entry) { if (entry->table_hton == hton && From 3b3f931570266487d9a9a2536514fe37b5297b37 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Sat, 21 Mar 2020 17:59:43 +0400 Subject: [PATCH 3/7] Discovery counters: my_atomic to Atomic_counter --- sql/handler.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 5f69a70d5e2..178830a87b1 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -440,9 +440,9 @@ static int ha_finish_errors(void) return 0; } -static volatile int32 need_full_discover_for_existence= 0; -static volatile int32 engines_with_discover_file_names= 0; -static volatile int32 engines_with_discover= 0; +static Atomic_counter need_full_discover_for_existence(0); +static Atomic_counter engines_with_discover_file_names(0); +static Atomic_counter engines_with_discover(0); static int full_discover_for_existence(handlerton *, const char *, const char *) { return 0; } @@ -464,13 +464,13 @@ static int hton_ext_based_table_discovery(handlerton *hton, LEX_CSTRING *db, static void update_discovery_counters(handlerton *hton, int val) { if (hton->discover_table_existence == full_discover_for_existence) - my_atomic_add32(&need_full_discover_for_existence, val); + need_full_discover_for_existence+= val; if (hton->discover_table_names && hton->tablefile_extensions[0]) - my_atomic_add32(&engines_with_discover_file_names, val); + engines_with_discover_file_names+= val; if (hton->discover_table) - my_atomic_add32(&engines_with_discover, val); + engines_with_discover+= val; } int ha_finalize_handlerton(st_plugin_int *plugin) From 62687801ffedc8521e3dbb111f26e7668902949c Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Sat, 21 Mar 2020 18:36:31 +0400 Subject: [PATCH 4/7] tc_active_instances: my_atomic to std::atomic --- sql/mysqld.cc | 2 +- sql/table_cache.cc | 34 +++++++++++++++++++++------------- sql/table_cache.h | 3 ++- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c33dc566f04..563aee8b9d4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7831,7 +7831,7 @@ SHOW_VAR status_vars[]= { {"Subquery_cache_miss", (char*) &subquery_cache_miss, SHOW_LONG}, {"Table_locks_immediate", (char*) &locks_immediate, SHOW_LONG}, {"Table_locks_waited", (char*) &locks_waited, SHOW_LONG}, - {"Table_open_cache_active_instances", (char*) &tc_active_instances, SHOW_UINT}, + {"Table_open_cache_active_instances", (char*) &show_tc_active_instances, SHOW_SIMPLE_FUNC}, {"Table_open_cache_hits", (char*) offsetof(STATUS_VAR, table_open_cache_hits), SHOW_LONGLONG_STATUS}, {"Table_open_cache_misses", (char*) offsetof(STATUS_VAR, table_open_cache_misses), SHOW_LONGLONG_STATUS}, {"Table_open_cache_overflows", (char*) offsetof(STATUS_VAR, table_open_cache_overflows), SHOW_LONGLONG_STATUS}, diff --git a/sql/table_cache.cc b/sql/table_cache.cc index 0743525b944..15255c56083 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -56,7 +56,7 @@ ulong tdc_size; /**< Table definition cache threshold for LRU eviction. */ ulong tc_size; /**< Table cache threshold for LRU eviction. */ uint32 tc_instances; -uint32 tc_active_instances= 1; +static std::atomic tc_active_instances(1); static std::atomic tc_contention_warning_reported; /** Data collections. */ @@ -163,7 +163,7 @@ struct Table_cache_instance overhead on TABLE object release. All other table cache mutex acquistions are considered out of hot path and are not instrumented either. */ - void lock_and_check_contention(uint32 n_instances, uint32 instance) + void lock_and_check_contention(uint32_t n_instances, uint32_t instance) { if (mysql_mutex_trylock(&LOCK_table_cache)) { @@ -172,11 +172,10 @@ struct Table_cache_instance { if (n_instances < tc_instances) { - if (my_atomic_cas32_weak_explicit((int32*) &tc_active_instances, - (int32*) &n_instances, - (int32) n_instances + 1, - MY_MEMORY_ORDER_RELAXED, - MY_MEMORY_ORDER_RELAXED)) + if (tc_active_instances. + compare_exchange_weak(n_instances, n_instances + 1, + std::memory_order_relaxed, + std::memory_order_relaxed)) { sql_print_information("Detected table cache mutex contention at instance %d: " "%d%% waits. Additional table cache instance " @@ -354,8 +353,8 @@ void tc_purge(bool mark_flushed) void tc_add_table(THD *thd, TABLE *table) { - uint32 i= thd->thread_id % my_atomic_load32_explicit((int32*) &tc_active_instances, - MY_MEMORY_ORDER_RELAXED); + uint32_t i= + thd->thread_id % tc_active_instances.load(std::memory_order_relaxed); TABLE *LRU_table= 0; TDC_element *element= table->s->tdc; @@ -408,10 +407,8 @@ void tc_add_table(THD *thd, TABLE *table) TABLE *tc_acquire_table(THD *thd, TDC_element *element) { - uint32 n_instances= - my_atomic_load32_explicit((int32*) &tc_active_instances, - MY_MEMORY_ORDER_RELAXED); - uint32 i= thd->thread_id % n_instances; + uint32_t n_instances= tc_active_instances.load(std::memory_order_relaxed); + uint32_t i= thd->thread_id % n_instances; TABLE *table; tc[i].lock_and_check_contention(n_instances, i); @@ -1342,3 +1339,14 @@ int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, } return res; } + + +int show_tc_active_instances(THD *thd, SHOW_VAR *var, char *buff, + enum enum_var_type scope) +{ + var->type= SHOW_UINT; + var->value= buff; + *(reinterpret_cast(buff))= + tc_active_instances.load(std::memory_order_relaxed); + return 0; +} diff --git a/sql/table_cache.h b/sql/table_cache.h index 611980c615f..3be7b5fe413 100644 --- a/sql/table_cache.h +++ b/sql/table_cache.h @@ -71,7 +71,6 @@ enum enum_tdc_remove_table_type extern ulong tdc_size; extern ulong tc_size; extern uint32 tc_instances; -extern uint32 tc_active_instances; extern bool tdc_init(void); extern void tdc_start_shutdown(void); @@ -98,6 +97,8 @@ extern int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, bool no_dups= false); extern uint tc_records(void); +int show_tc_active_instances(THD *thd, SHOW_VAR *var, char *buff, + enum enum_var_type scope); extern void tc_purge(bool mark_flushed= false); extern void tc_add_table(THD *thd, TABLE *table); extern void tc_release_table(TABLE *table); From 6acddd5367d51debb8ddf797a4a90f3e1d3c8a27 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Sat, 21 Mar 2020 19:46:49 +0400 Subject: [PATCH 5/7] global_query_id: my_atomic to Atomic_counter --- sql/mysqld.cc | 2 +- sql/mysqld.h | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 563aee8b9d4..a5f1d396ff5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -483,7 +483,7 @@ ulonglong test_flags; ulonglong query_cache_size=0; ulong query_cache_limit=0; ulong executed_events=0; -query_id_t global_query_id; +Atomic_counter global_query_id; ulong aborted_threads, aborted_connects, aborted_connects_preauth; ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size; ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use; diff --git a/sql/mysqld.h b/sql/mysqld.h index 44db6c6216b..4d502afa428 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -23,7 +23,6 @@ #include "sql_bitmap.h" /* Bitmap */ #include "my_decimal.h" /* my_decimal */ #include "mysql_com.h" /* SERVER_VERSION_LENGTH */ -#include "my_atomic.h" #include "my_counter.h" #include "mysql/psi/mysql_file.h" /* MYSQL_FILE */ #include "mysql/psi/mysql_socket.h" /* MYSQL_SOCKET */ @@ -763,17 +762,17 @@ enum enum_query_type /* query_id */ -extern query_id_t global_query_id; +extern Atomic_counter global_query_id; /* increment query_id and return it. */ inline __attribute__((warn_unused_result)) query_id_t next_query_id() { - return my_atomic_add64_explicit(&global_query_id, 1, MY_MEMORY_ORDER_RELAXED); + return global_query_id++; } inline query_id_t get_query_id() { - return my_atomic_load64_explicit(&global_query_id, MY_MEMORY_ORDER_RELAXED); + return global_query_id; } /* increment global_thread_id and return it. */ From 81f700015e746ac590b55bcb21bf21ba0d6febfc Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Sat, 21 Mar 2020 19:49:46 +0400 Subject: [PATCH 6/7] Cleanup my_atomic.h includes my_atomic.h is included indirectly anyways. --- storage/innobase/include/srv0mon.h | 1 - storage/maria/ma_loghandler.c | 1 - storage/maria/unittest/lockman-t.c | 1 - storage/maria/unittest/lockman1-t.c | 1 - storage/maria/unittest/lockman2-t.c | 1 - storage/maria/unittest/trnman-t.c | 1 - storage/perfschema/ha_perfschema.cc | 1 - unittest/mysys/thr_template.c | 1 - 8 files changed, 8 deletions(-) diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index 5a4d424981e..369892aa287 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -30,7 +30,6 @@ Created 12/15/2009 Jimmy Yang #define srv0mon_h #include "univ.i" -#include "my_atomic.h" #ifndef __STDC_LIMIT_MACROS /* Required for FreeBSD so that INT64_MAX is defined. */ diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index a6f41ec7329..d943666065a 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -470,7 +470,6 @@ static ulonglong flush_start= 0; #define TRANSLOG_CLSN_LEN_BITS 0xC0 /* Mask to get compressed LSN length */ -#include /* an array that maps id of a MARIA_SHARE to this MARIA_SHARE */ static MARIA_SHARE **id_to_share= NULL; diff --git a/storage/maria/unittest/lockman-t.c b/storage/maria/unittest/lockman-t.c index 669fd9ecc72..222618acf89 100644 --- a/storage/maria/unittest/lockman-t.c +++ b/storage/maria/unittest/lockman-t.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "../lockman.h" diff --git a/storage/maria/unittest/lockman1-t.c b/storage/maria/unittest/lockman1-t.c index 2a3cb291e3d..986ac73e2f5 100644 --- a/storage/maria/unittest/lockman1-t.c +++ b/storage/maria/unittest/lockman1-t.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "../lockman.h" #include "../tablockman.h" diff --git a/storage/maria/unittest/lockman2-t.c b/storage/maria/unittest/lockman2-t.c index ee3e2d2bd6b..7f9ed3cc50e 100644 --- a/storage/maria/unittest/lockman2-t.c +++ b/storage/maria/unittest/lockman2-t.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "../tablockman.h" diff --git a/storage/maria/unittest/trnman-t.c b/storage/maria/unittest/trnman-t.c index 00e84cb2456..3d19116dbbc 100644 --- a/storage/maria/unittest/trnman-t.c +++ b/storage/maria/unittest/trnman-t.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include "../trnman.h" diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc index c6077d7aa56..8860046fa26 100644 --- a/storage/perfschema/ha_perfschema.cc +++ b/storage/perfschema/ha_perfschema.cc @@ -27,7 +27,6 @@ #include "sql_plugin.h" #include "my_pthread.h" -#include "my_atomic.h" #include "ha_perfschema.h" #include "pfs_engine_table.h" #include "pfs_column_values.h" diff --git a/unittest/mysys/thr_template.c b/unittest/mysys/thr_template.c index 7aab89dcf87..42e035d911c 100644 --- a/unittest/mysys/thr_template.c +++ b/unittest/mysys/thr_template.c @@ -16,7 +16,6 @@ #include #include -#include #include volatile uint32 bad; From f7599f47999bb197dba36e54d0d5677b3b15f12a Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 23 Mar 2020 13:13:20 +0530 Subject: [PATCH 7/7] MDEV-21792 Server aborts upon attempt to create foreign key on spatial field - mbmaxlen is always 0 for binary field. Ignore the assert of checking field->prefix_len % field->col->mbmaxlen == 0. --- mysql-test/suite/innodb/r/foreign_key.result | 4 ++++ mysql-test/suite/innodb/t/foreign_key.test | 8 ++++++++ storage/innobase/dict/dict0dict.cc | 3 ++- storage/innobase/include/dict0mem.h | 5 ++++- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 288b6bb835d..dc88643fcf9 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -522,3 +522,7 @@ test.t1 check status OK DROP TABLE t1; SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; # End of 10.2 tests +CREATE TABLE t1 (a GEOMETRY, INDEX(a(8)), +FOREIGN KEY (a) REFERENCES x (xx)) ENGINE=InnoDB; +ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") +# End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 06cab983656..672539b9271 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -498,4 +498,12 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; --echo # End of 10.2 tests +# MDEV-21792 Server aborts upon attempt to create foreign key on spatial field +# Fail to create foreign key for spatial fields +--error ER_CANT_CREATE_TABLE +CREATE TABLE t1 (a GEOMETRY, INDEX(a(8)), + FOREIGN KEY (a) REFERENCES x (xx)) ENGINE=InnoDB; + +-- echo # End of 10.4 tests + --source include/wait_until_count_sessions.inc diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 29d33643c75..947fce1ae3a 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1839,7 +1839,8 @@ dict_index_add_to_cache( > field->col->max_prefix) { /* Set the max_prefix value based on the prefix_len. */ - ut_ad(field->prefix_len % field->col->mbmaxlen == 0); + ut_ad(field->col->is_binary() + || field->prefix_len % field->col->mbmaxlen == 0); field->col->max_prefix = field->prefix_len; } ut_ad(field->col->ord_part == 1); diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 36721f1942a..31f10f6f9a9 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 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 @@ -733,6 +733,9 @@ public: | CHAR_COLL_MASK << 16 | DATA_LONG_TRUE_VARCHAR)); } + + /** @return whether the column values are comparable by memcmp() */ + inline bool is_binary() const { return prtype & DATA_BINARY_TYPE; } }; /** Index information put in a list of virtual column structure. Index