diff --git a/mysql-test/suite/innodb/r/innodb_force_recovery_rollback.result b/mysql-test/suite/innodb/r/innodb_force_recovery_rollback.result index c2db4bed2f93d..59f0dd0be289f 100644 --- a/mysql-test/suite/innodb/r/innodb_force_recovery_rollback.result +++ b/mysql-test/suite/innodb/r/innodb_force_recovery_rollback.result @@ -16,3 +16,7 @@ connection default; SELECT * FROM t0 LIMIT 0 LOCK IN SHARE MODE; a DROP TABLE t0,t1; +# +# MDEV-38942 i_s_dict_fill_sys_tables() aborts when reading +# INNODB_SYS_TABLES after innodb_force_recovery +# diff --git a/mysql-test/suite/innodb/t/innodb_force_recovery_rollback.test b/mysql-test/suite/innodb/t/innodb_force_recovery_rollback.test index f1d14c45aafba..e712a43c9df5b 100644 --- a/mysql-test/suite/innodb/t/innodb_force_recovery_rollback.test +++ b/mysql-test/suite/innodb/t/innodb_force_recovery_rollback.test @@ -1,5 +1,6 @@ --source include/have_innodb.inc --source include/have_sequence.inc +--source include/maybe_debug.inc # We will kill and restart the server. --source include/not_embedded.inc @@ -33,3 +34,42 @@ connection default; # The LIMIT 0 works around MDEV-22889 InnoDB occasionally breaks ACID SELECT * FROM t0 LIMIT 0 LOCK IN SHARE MODE; DROP TABLE t0,t1; + +--echo # +--echo # MDEV-38942 i_s_dict_fill_sys_tables() aborts when reading +--echo # INNODB_SYS_TABLES after innodb_force_recovery +--echo # + +if ($have_debug) +{ +--disable_query_log +--disable_result_log +--let $restart_noprint=2 + +connect (con1,localhost,root,,,); +SET DEBUG_SYNC='create_table_inserted SIGNAL created WAIT_FOR ever'; +send CREATE TABLE t1 (a INT) ENGINE=InnoDB; + +connection default; +SET DEBUG_SYNC='now WAIT_FOR created'; +SET GLOBAL innodb_log_checkpoint_now=ON; + +--let $restart_parameters= --innodb-force-recovery=4 +--let $shutdown_timeout=0 +--source include/restart_mysqld.inc +--let $restart_parameters= +--let $shutdown_timeout= +--disable_result_log +--disable_query_log + +disconnect con1; +connection default; +SELECT name FROM information_schema.INNODB_SYS_TABLES WHERE name LIKE 'test/%'; + +--source include/restart_mysqld.inc +--disable_query_log + +--let $restart_noprint= +--enable_result_log +--enable_query_log +} diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index a49d2ab8e337c..a52e393d5163d 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -2186,7 +2186,8 @@ Do not load any columns or indexes. @param[in] rec SYS_TABLES record @param[out,own] table table, or nullptr @return error message -@retval nullptr on success */ +@retval nullptr on success, or if the record is not visible, in +which case *table will be nullptr */ const char *dict_load_table_low(mtr_t *mtr, bool uncommitted, const rec_t *rec, dict_table_t **table) { diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index aa27e38edc834..7a17fb13ca3a9 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -4497,7 +4497,8 @@ static int i_s_sys_error_handling(int err, THD *thd) @param rec record to read from (nullptr=use the dict_sys cache) @param table the converted dict_table_t @return error message -@retval nullptr on success */ +@retval nullptr on success, or if the record is not visible, in +which case *table will be nullptr*/ static const char *i_s_sys_tables_rec(const btr_pcur_t &pcur, mtr_t *mtr, const rec_t *rec, dict_table_t **table) { @@ -4560,7 +4561,7 @@ i_s_sys_tables_fill_table( } const char* err_msg; - dict_table_t* table_rec; + dict_table_t* table_rec = nullptr; /* Create and populate a dict_table_t structure with information from SYS_TABLES row */ @@ -4568,20 +4569,18 @@ i_s_sys_tables_fill_table( mtr.commit(); dict_sys.unlock(); - if (!err_msg) { + if (err_msg) { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_CANT_FIND_SYSTEM_REC, "%s", + err_msg); + } else if (table_rec) { err = i_s_dict_fill_sys_tables( thd, table_rec, tables->table); if (err) { err = i_s_sys_error_handling(err, thd); - if (table_rec) { - dict_mem_table_free(table_rec); - } + dict_mem_table_free(table_rec); goto func_exit; } - } else { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_CANT_FIND_SYSTEM_REC, "%s", - err_msg); } if (table_rec) { diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 71d4d5ad250de..6e66c8f5ecd44 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2081,6 +2081,8 @@ row_create_table_for_mysql( que_run_threads(thr); + DEBUG_SYNC_C("create_table_inserted"); + dberr_t err = trx->error_state; if (err != DB_SUCCESS) {