From 77fb7ccba41e9a901053ffc4fdc461968f6f616f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 4 Dec 2017 16:26:14 +0200 Subject: [PATCH] Follow-up fix to MDEV-13201 Assertion `srv_undo_sources || ...` failed on shutdown during DDL operation Introduce the debug flag trx_t::persistent_stats to suppress the assertion for the updates of persistent statistics during fast shutdown. dict_stats_exec_sql(): Do execute the statement even though shutdown has been initiated. --- mysql-test/suite/innodb/r/truncate_restart.result | 3 +-- mysql-test/suite/innodb/t/truncate_restart.test | 4 +--- storage/innobase/btr/btr0defragment.cc | 2 ++ storage/innobase/dict/dict0stats.cc | 12 ++++-------- storage/innobase/dict/dict0stats_bg.cc | 2 ++ storage/innobase/handler/ha_innodb.cc | 5 +++++ storage/innobase/include/trx0trx.h | 3 +++ storage/innobase/trx/trx0purge.cc | 3 ++- storage/innobase/trx/trx0trx.cc | 1 + 9 files changed, 21 insertions(+), 14 deletions(-) diff --git a/mysql-test/suite/innodb/r/truncate_restart.result b/mysql-test/suite/innodb/r/truncate_restart.result index 169a56a004ebb..b6d1412437176 100644 --- a/mysql-test/suite/innodb/r/truncate_restart.result +++ b/mysql-test/suite/innodb/r/truncate_restart.result @@ -1,6 +1,5 @@ -call mtr.add_suppression("InnoDB: Cannot save table statistics for table `test`\\.`t1`: Persistent statistics do not exist"); SET GLOBAL innodb_stats_persistent= ON; -CREATE TABLE t1 (t TEXT) ENGINE=InnoDB; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB STATS_PERSISTENT=1; connect con1,localhost,root,,test; SET DEBUG_SYNC='ib_trunc_table_trunc_completing SIGNAL committed WAIT_FOR ever'; TRUNCATE TABLE t1; diff --git a/mysql-test/suite/innodb/t/truncate_restart.test b/mysql-test/suite/innodb/t/truncate_restart.test index 92f09ac89b113..60a3d83cd81d0 100644 --- a/mysql-test/suite/innodb/t/truncate_restart.test +++ b/mysql-test/suite/innodb/t/truncate_restart.test @@ -2,10 +2,8 @@ --source include/have_debug.inc --source include/have_debug_sync.inc -call mtr.add_suppression("InnoDB: Cannot save table statistics for table `test`\\.`t1`: Persistent statistics do not exist"); - SET GLOBAL innodb_stats_persistent= ON; -CREATE TABLE t1 (t TEXT) ENGINE=InnoDB; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB STATS_PERSISTENT=1; --connect (con1,localhost,root,,test) SET DEBUG_SYNC='ib_trunc_table_trunc_completing SIGNAL committed WAIT_FOR ever'; --send diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc index 259ef5ef6de68..cdbe47d48f83e 100644 --- a/storage/innobase/btr/btr0defragment.cc +++ b/storage/innobase/btr/btr0defragment.cc @@ -831,6 +831,7 @@ DECLARE_THREAD(btr_defragment_thread)(void*) mtr_commit(&mtr); /* Reaching the end of the index. */ dict_stats_empty_defrag_stats(index); + ut_d(trx->persistent_stats = true); ++trx->will_lock; dberr_t err = dict_stats_save_defrag_stats(index, trx); if (err == DB_SUCCESS) { @@ -849,6 +850,7 @@ DECLARE_THREAD(btr_defragment_thread)(void*) trx_commit_for_mysql(trx); } + ut_d(trx->persistent_stats = false); btr_defragment_remove_item(item); } } diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 8050e8009ef4d..9afa228661d26 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -287,14 +287,6 @@ dict_stats_exec_sql( { dberr_t err; - extern bool dict_stats_start_shutdown; - - if (dict_stats_start_shutdown - || !dict_stats_persistent_storage_check(true)) { - pars_info_free(pinfo); - return(DB_STATS_DO_NOT_EXIST); - } - err = que_eval_sql(pinfo, sql, FALSE, trx); /* pinfo is freed here */ DBUG_EXECUTE_IF("stats_index_error", @@ -2276,6 +2268,8 @@ dict_stats_save_index_stat( char db_utf8[MAX_DB_UTF8_LEN]; char table_utf8[MAX_TABLE_UTF8_LEN]; + ut_ad(trx->persistent_stats || trx->in_mysql_trx_list); + dict_fs2utf8(index->table->name.m_name, db_utf8, sizeof(db_utf8), table_utf8, sizeof(table_utf8)); @@ -2401,6 +2395,8 @@ dict_stats_save( char db_utf8[MAX_DB_UTF8_LEN]; char table_utf8[MAX_TABLE_UTF8_LEN]; + ut_ad(trx->persistent_stats || trx->in_mysql_trx_list); + if (table_orig->is_readable()) { } else { return (dict_stats_report_error(table_orig)); diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index be97282dbfa4d..0f76c73bc9667 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -444,6 +444,7 @@ DECLARE_THREAD(dict_stats_thread)(void*) #endif /* UNIV_PFS_THREAD */ trx_t* trx = trx_allocate_for_background(); + ut_d(trx->persistent_stats = true); while (!dict_stats_start_shutdown) { @@ -476,6 +477,7 @@ DECLARE_THREAD(dict_stats_thread)(void*) os_event_reset(dict_stats_event); } + ut_d(trx->persistent_stats = false); trx_free_for_background(trx); srv_dict_stats_thread_active = false; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 40b195d684ff8..e02fb953a4890 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6468,9 +6468,12 @@ ha_innobase::open(const char* name, int, uint) if (alloc) { trx = trx_allocate_for_background(); } + ut_ad(!trx->persistent_stats); + ut_d(trx->persistent_stats = true); ++trx->will_lock; dict_stats_init(ib_table, trx); innobase_commit_low(trx); + ut_d(trx->persistent_stats = false); if (alloc) { trx_free_for_background(trx); } @@ -14592,6 +14595,7 @@ ha_innobase::info_low( on the mysql.innodb_table_stats, mysql.innodb_index_stats tables. */ trx_t* trx = trx_allocate_for_background(); + ut_d(trx->persistent_stats = true); ++trx->will_lock; ret = dict_stats_update(ib_table, opt, trx); @@ -14604,6 +14608,7 @@ ha_innobase::info_low( trx_commit_for_mysql(trx); } + ut_d(trx->persistent_stats = false); trx_free_for_background(trx); if (ret != DB_SUCCESS) { diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index b2d4952318cc9..001d3650bfeec 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -1123,6 +1123,9 @@ struct trx_t { mysql_trx_list; /*!< list of transactions created for MySQL; protected by trx_sys->mutex */ #ifdef UNIV_DEBUG + /** whether this transaction is updating persistent statistics + (used for silencing a debug assertion at shutdown) */ + bool persistent_stats; bool in_mysql_trx_list; /*!< true if in trx_sys->mysql_trx_list */ diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index c04fd5353a376..61c36637a4ea4 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -301,7 +301,8 @@ trx_purge_add_update_undo_to_history( && purge_sys->state == PURGE_STATE_INIT) || (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND && purge_sys->state == PURGE_STATE_DISABLED) - || ((trx->undo_no == 0 || trx->in_mysql_trx_list) + || ((trx->undo_no == 0 || trx->in_mysql_trx_list + || trx->persistent_stats) && srv_fast_shutdown)); /* Add the log as the first in the history list */ diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index dc8e115d2d169..ed334207b4c13 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -553,6 +553,7 @@ trx_validate_state_before_free(trx_t* trx) ut_ad(!trx->declared_to_be_inside_innodb); ut_ad(!trx->n_mysql_tables_in_use); ut_ad(!trx->mysql_n_tables_locked); + ut_ad(!trx->persistent_stats); if (trx->declared_to_be_inside_innodb) {