diff options
author | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2019-09-23 13:25:11 +0530 |
---|---|---|
committer | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2019-09-23 13:46:24 +0530 |
commit | dff55817cd868eedffe6ce0539764568df1d614f (patch) | |
tree | abba5259e0677342835b1c22c322a71ea978dc26 | |
parent | 66376a9be217eba20944e9ca2161a7f492a71398 (diff) | |
download | mariadb-git-10.5-MDEV-16678.tar.gz |
- Reverted 2c4844c9e76427525e8c39a2d72686085efe89c3. The scenario10.5-MDEV-16678
become useless after purge thread uses MDL
-rw-r--r-- | mysql-test/suite/innodb/r/instant_alter_purge.result | 22 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/purge_thread_shutdown.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/instant_alter_purge.test | 38 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 8 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 62 | ||||
-rw-r--r-- | storage/innobase/row/row0purge.cc | 8 |
6 files changed, 7 insertions, 133 deletions
diff --git a/mysql-test/suite/innodb/r/instant_alter_purge.result b/mysql-test/suite/innodb/r/instant_alter_purge.result index a3643610f04..1179ff62ecc 100644 --- a/mysql-test/suite/innodb/r/instant_alter_purge.result +++ b/mysql-test/suite/innodb/r/instant_alter_purge.result @@ -21,26 +21,4 @@ ALTER TABLE t1 DROP extra; disconnect prevent_purge; InnoDB 0 transactions not purged DROP TABLE t1; -# -# MDEV-17813 Crash in instant ALTER TABLE due to purge -# concurrently emptying table -# -CREATE TABLE t1 (f2 INT) ENGINE=InnoDB; -INSERT INTO t1 SET f2=1; -ALTER TABLE t1 ADD COLUMN f1 INT; -connect purge_control,localhost,root; -START TRANSACTION WITH CONSISTENT SNAPSHOT; -connection default; -DELETE FROM t1; -SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL go WAIT_FOR do'; -ALTER TABLE t1 ADD COLUMN f3 INT; -connection purge_control; -SET DEBUG_SYNC='now WAIT_FOR go'; -COMMIT; -InnoDB 0 transactions not purged -SET DEBUG_SYNC='now SIGNAL do'; -disconnect purge_control; -connection default; -SET DEBUG_SYNC=RESET; -DROP TABLE t1; SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/purge_thread_shutdown.result b/mysql-test/suite/innodb/r/purge_thread_shutdown.result index a87cba89917..f1b0cb07ce8 100644 --- a/mysql-test/suite/innodb/r/purge_thread_shutdown.result +++ b/mysql-test/suite/innodb/r/purge_thread_shutdown.result @@ -6,6 +6,7 @@ select user,state from information_schema.processlist order by 2; user state root root Filling schema table +system user InnoDB fts optimize thread system user InnoDB purge coordinator system user InnoDB purge worker system user InnoDB purge worker @@ -19,6 +20,7 @@ disconnect con1; select user,state from information_schema.processlist order by 2; user state root Filling schema table +system user InnoDB fts optimize thread system user InnoDB purge coordinator system user InnoDB purge worker system user InnoDB purge worker diff --git a/mysql-test/suite/innodb/t/instant_alter_purge.test b/mysql-test/suite/innodb/t/instant_alter_purge.test index 152d200d977..9ccf3347d7b 100644 --- a/mysql-test/suite/innodb/t/instant_alter_purge.test +++ b/mysql-test/suite/innodb/t/instant_alter_purge.test @@ -34,42 +34,4 @@ disconnect prevent_purge; let $wait_all_purged= 0; --source include/wait_all_purged.inc DROP TABLE t1; - ---echo # ---echo # MDEV-17813 Crash in instant ALTER TABLE due to purge ---echo # concurrently emptying table ---echo # -CREATE TABLE t1 (f2 INT) ENGINE=InnoDB; -INSERT INTO t1 SET f2=1; -ALTER TABLE t1 ADD COLUMN f1 INT; - -connect (purge_control,localhost,root); -START TRANSACTION WITH CONSISTENT SNAPSHOT; - -connection default; -DELETE FROM t1; - -if ($have_debug) { -SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL go WAIT_FOR do'; -} -send ALTER TABLE t1 ADD COLUMN f3 INT; - -connection purge_control; -if ($have_debug) { -SET DEBUG_SYNC='now WAIT_FOR go'; -} -COMMIT; ---source include/wait_all_purged.inc -if ($have_debug) { -SET DEBUG_SYNC='now SIGNAL do'; -} -disconnect purge_control; - -connection default; -reap; -if ($have_debug) { -SET DEBUG_SYNC=RESET; -} -DROP TABLE t1; - SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 63236ea2342..b78a103ed5b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5931,14 +5931,6 @@ initialize_auto_increment(dict_table_t* table, const Field* field) int ha_innobase::open(const char* name, int, uint) { - /* TODO: If trx_rollback_recovered(bool all=false) is ever - removed, the first-time open() must hold (or acquire and release) - a table lock that conflicts with trx_resurrect_table_locks(), - to ensure that any recovered incomplete ALTER TABLE will have been - rolled back. Otherwise, dict_table_t::instant could be cleared by - the rollback invoking dict_index_t::clear_instant_alter() while - open table handles exist in client connections. */ - char norm_name[FN_REFLEN]; DBUG_ENTER("ha_innobase::open"); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 2c8328a42bb..b4e269f7a94 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -140,30 +140,6 @@ static const alter_table_operations INNOBASE_ALTER_INSTANT | ALTER_RENAME_INDEX | ALTER_DROP_VIRTUAL_COLUMN; -/** Acquire a page latch on the possible metadata record, -to prevent concurrent invocation of dict_index_t::clear_instant_alter() -by purge when the table turns out to be empty. -@param[in,out] index clustered index -@param[in,out] mtr mini-transaction */ -static void instant_metadata_lock(dict_index_t& index, mtr_t& mtr) -{ - DBUG_ASSERT(index.is_primary()); - - if (!index.is_instant()) { - /* dict_index_t::clear_instant_alter() cannot be called. - No need for a latch. */ - return; - } - - btr_cur_t btr_cur; - btr_cur_open_at_index_side(true, &index, BTR_SEARCH_LEAF, - &btr_cur, 0, &mtr); - ut_ad(page_cur_is_before_first(btr_cur_get_page_cur(&btr_cur))); - ut_ad(page_is_leaf(btr_cur_get_page(&btr_cur))); - ut_ad(!page_has_prev(btr_cur_get_page(&btr_cur))); - ut_ad(!buf_block_get_page_zip(btr_cur_get_block(&btr_cur))); -} - /** Initialize instant->field_map. @tparam replace_dropped whether to point clustered index fields to instant->dropped[] @@ -242,16 +218,10 @@ inline void dict_table_t::prepare_instant(const dict_table_t& old, If that is the case, the instant ALTER TABLE would keep the InnoDB table in its current format. */ - dict_index_t& oindex = *old.indexes.start; + const dict_index_t& oindex = *old.indexes.start; dict_index_t& index = *indexes.start; first_alter_pos = 0; - mtr_t mtr; - mtr.start(); - /* Protect oindex.n_core_fields and others, so that - purge cannot invoke dict_index_t::clear_instant_alter(). */ - instant_metadata_lock(oindex, mtr); - for (unsigned i = 0; i + DATA_N_SYS_COLS < old.n_cols; i++) { if (col_map[i] != i) { first_alter_pos = 1 + i; @@ -424,7 +394,6 @@ found_j: DBUG_ASSERT(n_dropped() >= old.n_dropped()); DBUG_ASSERT(index.n_core_fields == oindex.n_core_fields); DBUG_ASSERT(index.n_core_null_bytes == oindex.n_core_null_bytes); - mtr.commit(); } /** Adjust index metadata for instant ADD/DROP/reorder COLUMN. @@ -444,15 +413,8 @@ inline void dict_index_t::instant_add_field(const dict_index_t& instant) DBUG_ASSERT(n_uniq == instant.n_uniq); DBUG_ASSERT(instant.n_fields >= n_fields); DBUG_ASSERT(instant.n_nullable >= n_nullable); - /* dict_table_t::prepare_instant() initialized n_core_fields - to be equal. However, after that purge could have emptied the - table and invoked dict_index_t::clear_instant_alter(). */ - DBUG_ASSERT(instant.n_core_fields <= n_core_fields); - DBUG_ASSERT(instant.n_core_null_bytes <= n_core_null_bytes); - DBUG_ASSERT(instant.n_core_fields == n_core_fields - || (!is_instant() && instant.is_instant())); - DBUG_ASSERT(instant.n_core_null_bytes == n_core_null_bytes - || (!is_instant() && instant.is_instant())); + DBUG_ASSERT(instant.n_core_fields == n_core_fields); + DBUG_ASSERT(instant.n_core_null_bytes == n_core_null_bytes); /* instant will have all fields (including ones for columns that have been or are being instantly dropped) in the same position @@ -755,11 +717,6 @@ inline void dict_table_t::rollback_instant( { ut_d(dict_sys.assert_locked()); dict_index_t* index = indexes.start; - mtr_t mtr; - mtr.start(); - /* Prevent concurrent execution of dict_index_t::clear_instant_alter() - by acquiring a latch on the leftmost leaf page. */ - instant_metadata_lock(*index, mtr); /* index->is_instant() does not necessarily hold here, because the table may have been emptied */ DBUG_ASSERT(old_n_cols >= DATA_N_SYS_COLS); @@ -814,7 +771,6 @@ inline void dict_table_t::rollback_instant( } index->fields = old_fields; - mtr.commit(); while ((index = dict_table_get_next_index(index)) != NULL) { if (index->to_be_dropped) { @@ -5628,12 +5584,6 @@ static bool innobase_instant_try( dict_table_t* user_table = ctx->old_table; dict_index_t* index = dict_table_get_first_index(user_table); - mtr_t mtr; - mtr.start(); - /* Prevent purge from calling dict_index_t::clear_instant_alter(), - to protect index->n_core_fields, index->table->instant and others - from changing during ctx->instant_column(). */ - instant_metadata_lock(*index, mtr); const unsigned n_old_fields = index->n_fields; const dict_col_t* old_cols = user_table->cols; DBUG_ASSERT(user_table->n_cols == ctx->old_n_cols); @@ -5641,11 +5591,6 @@ static bool innobase_instant_try( const bool metadata_changed = ctx->instant_column(); DBUG_ASSERT(index->n_fields >= n_old_fields); - /* Release the page latch. Between this and the next - btr_pcur_open_at_index_side(), data fields such as - index->n_core_fields and index->table->instant could change, - but we would handle that in empty_table: below. */ - mtr.commit(); /* The table may have been emptied and may have lost its 'instantness' during this ALTER TABLE. */ @@ -5801,6 +5746,7 @@ add_all_virtual: memset(roll_ptr, 0, sizeof roll_ptr); dtuple_t* entry = index->instant_metadata(*row, ctx->heap); + mtr_t mtr; mtr.start(); index->set_modified(mtr); btr_pcur_t pcur; diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 1e8cd1ada71..d072affa11b 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -108,6 +108,7 @@ row_purge_remove_clust_if_poss_low( mtr_t mtr; mtr.start(); + index->set_modified(mtr); if (!row_purge_reposition_pcur(mode, node, &mtr)) { /* The record was already removed. */ @@ -115,9 +116,6 @@ row_purge_remove_clust_if_poss_low( return true; } - ut_d(const bool was_instant = !!index->table->instant); - index->set_modified(mtr); - rec_t* rec = btr_pcur_get_rec(&node->pcur); ulint offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs_init(offsets_); @@ -157,10 +155,6 @@ row_purge_remove_clust_if_poss_low( } } - /* Prove that dict_index_t::clear_instant_alter() was - not called with index->table->instant != NULL. */ - ut_ad(!was_instant || index->table->instant); - func_exit: if (heap) { mem_heap_free(heap); |