diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-10-16 12:06:43 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-10-16 19:11:30 +0300 |
commit | 1eee3a3fb79e809943ff9e37b022660d155ad486 (patch) | |
tree | c45eb5b1f5f3ce8af2319db374a875d061233665 /storage | |
parent | b9418ed3332358e7209300739435c5e0aeb5ba70 (diff) | |
download | mariadb-git-1eee3a3fb79e809943ff9e37b022660d155ad486.tar.gz |
MDEV-13051 MySQL#86607 InnoDB crash after failed ADD INDEX and table_definition_cache eviction
There are two bugs related to failed ADD INDEX and
the InnoDB table cache eviction.
dict_table_close(): Try dropping failed ADD INDEX when releasing
the last table handle, not when releasing the last-but-one.
dict_table_remove_from_cache_low(): Do not invoke
row_merge_drop_indexes() after freeing all index metadata.
Instead, directly invoke row_merge_drop_indexes_dict() to
remove the metadata from the persistent data dictionary
and to free the index pages.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/dict/dict0dict.cc | 24 | ||||
-rw-r--r-- | storage/xtradb/dict/dict0dict.cc | 21 |
2 files changed, 15 insertions, 30 deletions
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 5967c51d263..11a4b892397 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2014, 2015, MariaDB Corporation. +Copyright (c) 2014, 2017, 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 @@ -570,15 +570,14 @@ dict_table_close( ut_ad(mutex_own(&dict_sys->mutex)); ut_a(table->n_ref_count > 0); - --table->n_ref_count; + const bool last_handle = !--table->n_ref_count; /* Force persistent stats re-read upon next open of the table so that FLUSH TABLE can be used to forcibly fetch stats from disk if they have been manually modified. We reset table->stat_initialized only if table reference count is 0 because we do not want too frequent stats re-reads (e.g. in other cases than FLUSH TABLE). */ - if (strchr(table->name, '/') != NULL - && table->n_ref_count == 0 + if (last_handle && strchr(table->name, '/') != NULL && dict_stats_is_persistent_enabled(table)) { dict_stats_deinit(table); @@ -598,11 +597,8 @@ dict_table_close( if (!dict_locked) { table_id_t table_id = table->id; - ibool drop_aborted; - - drop_aborted = try_drop + const bool drop_aborted = last_handle && try_drop && table->drop_aborted - && table->n_ref_count == 1 && dict_table_get_first_index(table); mutex_exit(&dict_sys->mutex); @@ -2087,8 +2083,9 @@ dict_table_remove_from_cache_low( } if (lru_evict && table->drop_aborted) { - /* Do as dict_table_try_drop_aborted() does. */ - + /* When evicting the table definition, + drop the orphan indexes from the data dictionary + and free the index pages. */ trx_t* trx = trx_allocate_for_background(); ut_ad(mutex_own(&dict_sys->mutex)); @@ -2099,12 +2096,7 @@ dict_table_remove_from_cache_low( trx->dict_operation_lock_mode = RW_X_LATCH; trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); - - /* Silence a debug assertion in row_merge_drop_indexes(). */ - ut_d(table->n_ref_count++); - row_merge_drop_indexes(trx, table, TRUE); - ut_d(table->n_ref_count--); - ut_ad(table->n_ref_count == 0); + row_merge_drop_indexes_dict(trx, table->id); trx_commit_for_mysql(trx); trx->dict_operation_lock_mode = 0; trx_free_for_background(trx); diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc index 798a7497645..a23b297e904 100644 --- a/storage/xtradb/dict/dict0dict.cc +++ b/storage/xtradb/dict/dict0dict.cc @@ -570,15 +570,14 @@ dict_table_close( ut_ad(mutex_own(&dict_sys->mutex)); ut_a(table->n_ref_count > 0); - --table->n_ref_count; + const bool last_handle = !--table->n_ref_count; /* Force persistent stats re-read upon next open of the table so that FLUSH TABLE can be used to forcibly fetch stats from disk if they have been manually modified. We reset table->stat_initialized only if table reference count is 0 because we do not want too frequent stats re-reads (e.g. in other cases than FLUSH TABLE). */ - if (strchr(table->name, '/') != NULL - && table->n_ref_count == 0 + if (last_handle && strchr(table->name, '/') != NULL && dict_stats_is_persistent_enabled(table)) { dict_stats_deinit(table); @@ -598,11 +597,8 @@ dict_table_close( if (!dict_locked) { table_id_t table_id = table->id; - ibool drop_aborted; - - drop_aborted = try_drop + const bool drop_aborted = last_handle && try_drop && table->drop_aborted - && table->n_ref_count == 1 && dict_table_get_first_index(table); mutex_exit(&dict_sys->mutex); @@ -2096,8 +2092,9 @@ dict_table_remove_from_cache_low( } if (lru_evict && table->drop_aborted) { - /* Do as dict_table_try_drop_aborted() does. */ - + /* When evicting the table definition, + drop the orphan indexes from the data dictionary + and free the index pages. */ trx_t* trx = trx_allocate_for_background(); ut_ad(mutex_own(&dict_sys->mutex)); @@ -2108,12 +2105,8 @@ dict_table_remove_from_cache_low( trx->dict_operation_lock_mode = RW_X_LATCH; trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); + row_merge_drop_indexes_dict(trx, table->id); - /* Silence a debug assertion in row_merge_drop_indexes(). */ - ut_d(table->n_ref_count++); - row_merge_drop_indexes(trx, table, TRUE); - ut_d(table->n_ref_count--); - ut_ad(table->n_ref_count == 0); trx_commit_for_mysql(trx); trx->dict_operation_lock_mode = 0; trx_free_for_background(trx); |