diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2021-02-16 08:46:14 +0200 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2021-02-16 08:46:14 +0200 |
commit | a5bcec727b096f634e43f9031440cc1dc9e302c2 (patch) | |
tree | c1005cdf624719b0e97e318b0d11cd5ec81bfc52 | |
parent | d0defd1ea2af80a360332fd8c1e60a34e2289213 (diff) | |
download | mariadb-git-bb-10.4-MDEV-24865.tar.gz |
MDEV-24865 : Server crashes when truncate mysql user tablebb-10.4-MDEV-24865
For truncate we try to find out possible foreign key tables
using open_tables. However, table_list was not cleaned up
properly and there was no error handling. Fixed by cleaning
table_list and adding proper error handling.
-rw-r--r-- | mysql-test/suite/galera/r/galera_truncate.result | 11 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_truncate.test | 20 | ||||
-rw-r--r-- | sql/sql_truncate.cc | 23 | ||||
-rw-r--r-- | sql/wsrep_mysqld.cc | 45 | ||||
-rw-r--r-- | sql/wsrep_mysqld.h | 2 |
5 files changed, 71 insertions, 30 deletions
diff --git a/mysql-test/suite/galera/r/galera_truncate.result b/mysql-test/suite/galera/r/galera_truncate.result index c649d9bbaf9..c9a4bc854f8 100644 --- a/mysql-test/suite/galera/r/galera_truncate.result +++ b/mysql-test/suite/galera/r/galera_truncate.result @@ -32,6 +32,17 @@ SELECT AUTO_INCREMENT = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN ('t AUTO_INCREMENT = 1 1 1 +connection node_1; +TRUNCATE TABLE mysql.user; +ERROR 42S02: Table 'mysql.user' doesn't exist +TRUNCATE TABLE performance_schema.threads; +ERROR HY000: Invalid performance_schema usage +TRUNCATE TABLE information_schema.tables; +ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' +TRUNCATE TABLE mysql.innodb_index_stats; +TRUNCATE TABLE foo.bar; +ERROR 42S02: Table 'foo.bar' doesn't exist +TRUNCATE TABLE t1; DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; diff --git a/mysql-test/suite/galera/t/galera_truncate.test b/mysql-test/suite/galera/t/galera_truncate.test index 3c3ee56a23f..c3dd02017bb 100644 --- a/mysql-test/suite/galera/t/galera_truncate.test +++ b/mysql-test/suite/galera/t/galera_truncate.test @@ -3,8 +3,7 @@ # --source include/galera_cluster.inc ---source include/have_innodb.inc - +--source include/have_perfschema.inc # # Simple case # @@ -54,6 +53,23 @@ TRUNCATE TABLE t4; --connection node_2 SELECT AUTO_INCREMENT = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN ('t3', 't4'); + +# +# MDEV-24865 : Server crashes when truncate mysql user table +# +--connection node_1 + +--error ER_NO_SUCH_TABLE +TRUNCATE TABLE mysql.user; +--error ER_WRONG_PERFSCHEMA_USAGE +TRUNCATE TABLE performance_schema.threads; +--error ER_DBACCESS_DENIED_ERROR +TRUNCATE TABLE information_schema.tables; +TRUNCATE TABLE mysql.innodb_index_stats; +--error ER_NO_SUCH_TABLE +TRUNCATE TABLE foo.bar; +TRUNCATE TABLE t1; + DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index c3d347307a2..e7ecdda958e 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -416,20 +416,23 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) bool hton_can_recreate; #ifdef WITH_WSREP - if (WSREP(thd)) + if (WSREP(thd) && wsrep_thd_is_local(thd)) { wsrep::key_array keys; - wsrep_append_fk_parent_table(thd, table_ref, &keys); - if (keys.empty()) + /* Do not start TOI if table is not found */ + if (!wsrep_append_fk_parent_table(thd, table_ref, &keys)) { - WSREP_TO_ISOLATION_BEGIN_IF(table_ref->db.str, table_ref->table_name.str, NULL) + if (keys.empty()) { - DBUG_RETURN(TRUE); - } - } else { - WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, table_ref, &keys) - { - DBUG_RETURN(TRUE); + WSREP_TO_ISOLATION_BEGIN_IF(table_ref->db.str, table_ref->table_name.str, NULL) + { + DBUG_RETURN(TRUE); + } + } else { + WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, table_ref, &keys) + { + DBUG_RETURN(TRUE); + } } } } diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index c0f48cca9cd..5fbed9666c4 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1184,10 +1184,17 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr) key_arr->keys_len= 0; } -void +/*! + * @param thd thread + * @param tables list of tables + * @param keys prepared keys + + * @return true if parent table append was successfull, otherwise false. +*/ +bool wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* keys) { - if (!WSREP(thd) || !WSREP_CLIENT(thd)) return; + bool fail= false; TABLE_LIST *table; thd->release_transactional_locks(); @@ -1198,6 +1205,8 @@ wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* key open_tables(thd, &tables, &counter, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL)) { WSREP_DEBUG("unable to open table for FK checks for %s", thd->query()); + fail= true; + goto exit; } for (table= tables; table; table= table->next_local) @@ -1219,14 +1228,18 @@ wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* key } } +exit: /* close the table and release MDL locks */ close_thread_tables(thd); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); for (table= tables; table; table= table->next_local) { table->table= NULL; + table->next_global= NULL; table->mdl_request.ticket= NULL; } + + return fail; } /*! @@ -1965,7 +1978,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table, { DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI); - WSREP_DEBUG("TOI Begin"); + WSREP_DEBUG("TOI Begin for %s", WSREP_QUERY(thd)); if (wsrep_can_run_in_toi(thd, db, table, table_list) == false) { WSREP_DEBUG("No TOI for %s", WSREP_QUERY(thd)); @@ -2055,22 +2068,20 @@ static void wsrep_TOI_end(THD *thd) { wsrep_to_isolation--; wsrep::client_state& client_state(thd->wsrep_cs()); DBUG_ASSERT(wsrep_thd_is_local_toi(thd)); - WSREP_DEBUG("TO END: %lld: %s", client_state.toi_meta().seqno().get(), - WSREP_QUERY(thd)); - if (wsrep_thd_is_local_toi(thd)) + wsrep_set_SE_checkpoint(client_state.toi_meta().gtid()); + + int ret= client_state.leave_toi_local(wsrep::mutable_buffer()); + + if (!ret) { - wsrep_set_SE_checkpoint(client_state.toi_meta().gtid()); - int ret= client_state.leave_toi_local(wsrep::mutable_buffer()); - if (!ret) - { - WSREP_DEBUG("TO END: %lld", client_state.toi_meta().seqno().get()); - } - else - { - WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s", - ret, (thd->db.str ? thd->db.str : "(null)"), WSREP_QUERY(thd)); - } + WSREP_DEBUG("TO END: %lld: %s", + client_state.toi_meta().seqno().get(), WSREP_QUERY(thd)); + } + else + { + WSREP_WARN("TO isolation end failed for: %d, sql: %s", + ret, WSREP_QUERY(thd)); } } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 29b1c4cf1f4..2ec3943b5c2 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -212,7 +212,7 @@ wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout); extern void wsrep_last_committed_id (wsrep_gtid_t* gtid); extern int wsrep_check_opts(); extern void wsrep_prepend_PATH (const char* path); -void wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* table, wsrep::key_array* keys); +extern bool wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* table, wsrep::key_array* keys); /* Other global variables */ extern wsrep_seqno_t wsrep_locked_seqno; |