• Marko Mäkelä's avatar
    MDEV-22456 Dropping the adaptive hash index may cause DDL to lock up InnoDB · ad6171b9
    Marko Mäkelä authored
    If the InnoDB buffer pool contains many pages for a table or index
    that is being dropped or rebuilt, and if many of such pages are
    pointed to by the adaptive hash index, dropping the adaptive hash index
    may consume a lot of time.
    
    The time-consuming operation of dropping the adaptive hash index entries
    is being executed while the InnoDB data dictionary cache dict_sys is
    exclusively locked.
    
    It is not actually necessary to drop all adaptive hash index entries
    at the time a table or index is being dropped or rebuilt. We can let
    the LRU replacement policy of the buffer pool take care of this gradually.
    For this to work, we must detach the dict_table_t and dict_index_t
    objects from the main dict_sys cache, and once the last
    adaptive hash index entry for the detached table is removed
    (when the garbage page is evicted from the buffer pool) we can free
    the dict_table_t and dict_index_t object.
    
    Related to this, in MDEV-16283, we made ALTER TABLE...DISCARD TABLESPACE
    skip both the buffer pool eviction and the drop of the adaptive hash index.
    We shifted the burden to ALTER TABLE...IMPORT TABLESPACE or DROP TABLE.
    We can remove the eviction from DROP TABLE. We must retain the eviction
    in the ALTER TABLE...IMPORT TABLESPACE code path, so that in case the
    discarded table is being re-imported with the same tablespace identifier,
    the fresh data from the imported tablespace will replace any stale pages
    in the buffer pool.
    
    rpl.rpl_failed_drop_tbl_binlog: Remove the test. DROP TABLE can
    no longer be interrupted inside InnoDB.
    
    fseg_free_page(), fseg_free_step(), fseg_free_step_not_header(),
    fseg_free_page_low(), fseg_free_extent(): Remove the parameter
    that specifies whether the adaptive hash index should be dropped.
    
    btr_search_lazy_free(): Lazily free an index when the last
    reference to it is dropped from the adaptive hash index.
    
    buf_pool_clear_hash_index(): Declare static, and move to the
    same compilation unit with the bulk of the adaptive hash index
    code.
    
    dict_index_t::clone(), dict_index_t::clone_if_needed():
    Clone an index that is being rebuilt while adaptive hash index
    entries exist. The original index will be inserted into
    dict_table_t::freed_indexes and dict_index_t::set_freed()
    will be called.
    
    dict_index_t::set_freed(), dict_index_t::freed(): Note that
    or check whether the index has been freed. We will use the
    impossible page number 1 to denote this condition.
    
    dict_index_t::n_ahi_pages(): Replaces btr_search_info_get_ref_count().
    
    dict_index_t::detach_columns(): Move the assignment n_fields=0
    to ha_innobase_inplace_ctx::clear_added_indexes().
    We must have access to the columns when freeing the
    adaptive hash index. Note: dict_table_t::v_cols[] will remain
    valid. If virtual columns are dropped or added, the table
    definition will be reloaded in ha_innobase::commit_inplace_alter_table().
    
    buf_page_mtr_lock(): Drop a stale adaptive hash index if needed.
    
    We will also reduce the number of btr_get_search_latch() calls
    and enclose some more code inside #ifdef BTR_CUR_HASH_ADAPT
    in order to benefit cmake -DWITH_INNODB_AHI=OFF.
    ad6171b9
btr0sea.cc 53.3 KB