1. 15 May, 2020 5 commits
    • 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
    • Marko Mäkelä's avatar
      Amend af784385: Avoid vtable overhead · ff66d65a
      Marko Mäkelä authored
      When neither MSAN nor Valgrind are enabled, declare
      Field::mark_unused_memory_as_defined() as an empty inline function,
      instead of declaring it as a virtual function.
      ff66d65a
    • Eugene Kosov's avatar
      span cleanup · 1cac6d48
      Eugene Kosov authored
      1cac6d48
    • Monty's avatar
      Fix for using uninitialized memory · af784385
      Monty authored
      MDEV-22073 MSAN use-of-uninitialized-value in
      collect_statistics_for_table()
      
      Other things:
      innodb.analyze_table was changed to mainly test statistic
      collection. Was discussed with Marko.
      af784385
    • Monty's avatar
      Fixed bugs found by valgrind · 277aa85c
      Monty authored
      Other things:
      - Removed innodb_encryption_tables.test from valgrind as it
        takes a REALLY long time
      277aa85c
  2. 14 May, 2020 11 commits
  3. 13 May, 2020 2 commits
  4. 12 May, 2020 3 commits
    • Vlad Lesin's avatar
      MDEV-22398: mariabackup.innodb_xa_rollback fails on repeat · 218d20ff
      Vlad Lesin authored
      Flush LSN to system tablespace on innodb shutdown if XA is rolled back by
      mariabackup.
      218d20ff
    • Marko Mäkelä's avatar
      Cleanup: Remove InnoDB wrappers of thd_charset(), thd_query_safe() · 0e6a5786
      Marko Mäkelä authored
      innobase_get_charset(), innobase_get_stmt_safe(): Remove.
      It is more efficient and readable to invoke thd_charset()
      and thd_query_safe() directly, without a non-inlined wrapper function.
      0e6a5786
    • Marko Mäkelä's avatar
      MDEV-22529 thd_query_safe() isn’t, causing InnoDB to hang · a2560b00
      Marko Mäkelä authored
      The function thd_query_safe() is used in the implementation of the
      following INFORMATION_SCHEMA views:
      
          information_schema.innodb_trx
          information_schema.innodb_locks
          information_schema.innodb_lock_waits
          information_schema.rocksdb_trx
      
      The implementation of the InnoDB views is in trx_i_s_common_fill_table().
      This function invokes trx_i_s_possibly_fetch_data_into_cache(),
      which will acquire lock_sys->mutex and trx_sys->mutex in order to
      protect the set of active transactions and explicit locks.
      While holding those mutexes, it will traverse the collection of
      InnoDB transactions. For each transaction, thd_query_safe() will be
      invoked.
      
      When called via trx_i_s_common_fill_table(), thd_query_safe()
      is acquiring THD::LOCK_thd_data while holding the InnoDB locks.
      This will cause a deadlock with THD::awake() (such as executing
      KILL QUERY), because THD::awake() could invoke lock_trx_handle_wait(),
      which attempts to acquire lock_sys->mutex while already holding
      THD::lock_thd_data.
      
      thd_query_safe(): Invoke mysql_mutex_trylock() instead of
      mysql_mutex_lock(). Return the empty string if the mutex
      cannot be acquired without waiting.
      a2560b00
  5. 11 May, 2020 5 commits
  6. 09 May, 2020 1 commit
  7. 08 May, 2020 10 commits
  8. 07 May, 2020 2 commits
    • Marko Mäkelä's avatar
      MDEV-19344 innodb.innodb-change-buffer-recovery fails · 0dee57c6
      Marko Mäkelä authored
      The test was incompatible with ./mtr --repeat=2 until
      commit 2d6719d7
      fixed that.
      
      It turns out that the failing assertion that we disabled in
      commit 3db94d24
      is bogus and can fail when the change buffer is emptied
      during the last batch of crash recovery. The reason for this
      is the condition around the page_create_empty() call in
      page_cur_delete_rec(). The condition was removed in MariaDB
      Server 10.5 as part of MDEV-12353, in
      commit 7ae21b18 and
      commit f8a9f906.
      
      The bug that the assertion aimed to catch is MDEV-22497, which
      was fixed in commit 26aab96e.
      0dee57c6
    • Marko Mäkelä's avatar
      MDEV-22497 [ERROR] InnoDB: Unable to purge a record · 26aab96e
      Marko Mäkelä authored
      The InnoDB insert buffer was upgraded in MySQL 5.5 into a change
      buffer that also covers delete-mark and delete (purge) operations.
      
      There is an important constraint for delete operations: a B-tree
      leaf page must not become empty unless the entire tree becomes empty,
      consisting of an empty root page. Because change buffer merges only
      occur on a single leaf page at a time, delete operations must not be
      buffered if it is possible that the last record of the page could be
      deleted. (In that case, we would refuse to use the change buffer, and
      if we really delete the last record, we would shrink the index tree.)
      
      The function ibuf_get_volume_buffered_hash() is part of our insurance
      that the page would not become empty. It is supposed to map each
      buffered INSERT or DELETE_MARK record payload into a hash value.
      We will only count each such record as a distinct key if there is no
      hash collision. DELETE operations will always decrement the predicted
      number fo records in the page.
      
      Due to a bug in the function, we would actually compute the hash value
      not only on the record payload, but also on some following bytes,
      in case the record contains NULL values. In MySQL Bug #61104, we had
      some examples of this dating back to 2012. But back then, we failed to
      reproduce the bug, and in commit d84c9557
      we simply demoted the hard assertion to a message printout and a debug
      assertion failure.
      
      ibuf_get_volume_buffered_hash(): Correctly compute the hash value
      of the payload bytes only. Note: we will consider
      ('foo','bar'),(NULL,'foobar'),('foob','ar') to be equal, but this
      is not a problem, because in case of a hash collision, we could
      also consider ('boo','far') to be equal, and underestimate the number
      of records in the page, leading to refusing to buffer a DELETE.
      26aab96e
  9. 06 May, 2020 1 commit