1. 08 Sep, 2021 1 commit
    • Eugene Kosov's avatar
      TSAN: data race on vptr (ctor/dtor vs virtual call) · 78084fa7
      Eugene Kosov authored
        Read of size 8 at 0x7fecf2e75fc8 by thread T2 (mutexes: write M1318):
          #0 tpool::thread_pool_generic::submit_task(tpool::task*) /tpool/tpool_generic.cc:823:9 (mariadbd+0x25fd2d2)
          #1 (anonymous namespace)::aio_uring::thread_routine((anonymous namespace)::aio_uring*) /tpool/aio_liburing.cc:173:20 (mariadbd+0x260b21b)
          #2 void std::__invoke_impl<void, void (*)((anonymous namespace)::aio_uring*), (anonymous namespace)::aio_uring*>(std::__invoke_other, void (*&&)((anonymous namespace)::aio_uring*), (anonymous namespace)::aio_uring*&&) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14 (mariadbd+0x260c62a)
          #3 std::__invoke_result<void (*)((anonymous namespace)::aio_uring*), (anonymous namespace)::aio_uring*>::type std::__invoke<void (*)((anonymous namespace)::aio_uring*), (anonymous namespace)::aio_uring*>(void (*&&)((anonymous namespace)::aio_uring*), (anonymous namespace)::aio_uring*&&) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:96:14 (mariadbd+0x260c4ba)
          #4 void std::thread::_Invoker<std::tuple<void (*)((anonymous namespace)::aio_uring*), (anonymous namespace)::aio_uring*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:253:13 (mariadbd+0x260c442)
          #5 std::thread::_Invoker<std::tuple<void (*)((anonymous namespace)::aio_uring*), (anonymous namespace)::aio_uring*> >::operator()() /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:260:11 (mariadbd+0x260c3c5)
          #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)((anonymous namespace)::aio_uring*), (anonymous namespace)::aio_uring*> > >::_M_run() /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:211:13 (mariadbd+0x260c189)
          #7 <null> <null> (libstdc++.so.6+0xd230f)
      
        Previous write of size 8 at 0x7fecf2e75fc8 by main thread:
          #0 tpool::task::task(void (*)(void*), void*, tpool::task_group*) /tpool/task.cc:40:46 (mariadbd+0x260a138)
          #1 tpool::aiocb::aiocb() /tpool/tpool.h:147:13 (mariadbd+0x2355943)
          #2 void std::_Construct<tpool::aiocb>(tpool::aiocb*) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_construct.h:109:38 (mariadbd+0x2355845)
          #3 tpool::aiocb* std::__uninitialized_default_n_1<false>::__uninit_default_n<tpool::aiocb*, unsigned long>(tpool::aiocb*, unsigned long) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_uninitialized.h:579:3 (mariadbd+0x235576c)
          #4 tpool::aiocb* std::__uninitialized_default_n<tpool::aiocb*, unsigned long>(tpool::aiocb*, unsigned long) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_uninitialized.h:638:14 (mariadbd+0x23556e9)
          #5 tpool::aiocb* std::__uninitialized_default_n_a<tpool::aiocb*, unsigned long, tpool::aiocb>(tpool::aiocb*, unsigned long, std::allocator<tpool::aiocb>&) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_uninitialized.h:704:14 (mariadbd+0x2355641)
          #6 std::vector<tpool::aiocb, std::allocator<tpool::aiocb> >::_M_default_initialize(unsigned long) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_vector.h:1606:4 (mariadbd+0x2354f3d)
          #7 std::vector<tpool::aiocb, std::allocator<tpool::aiocb> >::vector(unsigned long, std::allocator<tpool::aiocb> const&) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_vector.h:512:9 (mariadbd+0x2354a19)
          #8 tpool::cache<tpool::aiocb>::cache(unsigned long, tpool::cache_notification_mode) /tpool/tpool_structs.h:73:20 (mariadbd+0x2354784)
          #9 io_slots::io_slots(int, int) /storage/innobase/os/os0file.cc:93:3 (mariadbd+0x235343b)
          #10 os_aio_init() /storage/innobase/os/os0file.cc:3780:22 (mariadbd+0x234ebce)
          #11 srv_start(bool) /storage/innobase/srv/srv0start.cc:1190:6 (mariadbd+0x256720c)
          #12 innodb_init(void*) /storage/innobase/handler/ha_innodb.cc:4188:8 (mariadbd+0x1ed3bda)
          #13 ha_initialize_handlerton(st_plugin_int*) /sql/handler.cc:659:31 (mariadbd+0xf7be06)
          #14 plugin_initialize(st_mem_root*, st_plugin_int*, int*, char**, bool) /sql/sql_plugin.cc:1463:9 (mariadbd+0x160fa1b)
          #15 plugin_init(int*, char**, int) /sql/sql_plugin.cc:1756:15 (mariadbd+0x160f07f)
          #16 init_server_components() /sql/mysqld.cc:5043:7 (mariadbd+0xd70fb2)
          #17 mysqld_main(int, char**) /sql/mysqld.cc:5655:7 (mariadbd+0xd6a9d7)
          #18 main /sql/main.cc:34:10 (mariadbd+0xd65d18)
      
      I think the report is incorrect: it's not possible to have such a race
      condition. I've checked it by reading the code and putting assertions.
      Namely, no aio I/O is possible before the end of os_aio_init().
      Most probably it's some bug in TSAN. But the patch fixes around 5 related
      reports and this is a step toward TSAN usefullness. Currently it reports too
      much noise.
      
      std::unique_ptr is a step toward https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#r11-avoid-calling-new-and-delete-explicitly
      There is no std::make_unique() in C++11, however.
      78084fa7
  2. 07 Sep, 2021 5 commits
  3. 06 Sep, 2021 13 commits
    • Vladislav Vaintroub's avatar
      Fix a false positive GCC5 warning. · b729c1a1
      Vladislav Vaintroub authored
      b729c1a1
    • Vladislav Vaintroub's avatar
      MDEV-26527 speedup appveyor build · d8943b0c
      Vladislav Vaintroub authored
      Define custom target for minimal testable build use it in appveyor.yml
      d8943b0c
    • Vladislav Vaintroub's avatar
      MDEV-26527 speedup appveyor build · 7dd85c0f
      Vladislav Vaintroub authored
      - set clone_depth to 1. Otherwise, appveyor spends
        4.5 minutes for the "git clone" alone
      
      - Use Ninja instead of msbuild, it is (a bit) faster
      
      - do not compile perfschema, or dynamic plugins
        to save time on compilation, or test execution.
      
      - use -DFAST_BUILD=1 to speedup build a little
      
      - increase number of parallel jobs used in build and test.
      - Exclude some slow tests from the main suite.
      7dd85c0f
    • Vladislav Vaintroub's avatar
      MDEV-26527 speedup appveyor build · 999d254c
      Vladislav Vaintroub authored
      Introduce -DFAST_BUILD parameter for a little faster build or test
      
      if set,
      - do not compile with /d2OptimizeHugeFunctions, this makes compilation
      of bison output much slower on optimized build
      - do not use runtime checks on debug build (RTC1). This slows down tests
      considerably
      999d254c
    • Vladislav Vaintroub's avatar
      MDEV-26527 speedup appveyor build · 16131a7e
      Vladislav Vaintroub authored
      Allow mysql_client_test to execute even if server/client auth plugins are
      not built. There is a single small test that requires qa_auth_client.
      16131a7e
    • Marko Mäkelä's avatar
      MDEV-26467: GCC 4.8.5 internal compiler error on ARMv8 · 2e39987f
      Marko Mäkelä authored
      We will disable some optimizations, because the function
      row_ins_clust_index_entry_low() would fail to compile
      ever since commit a73eedbf
      changed the definition of srw_mutex::wr_unlock() to use
      fetch_sub() instead of fetch_and().
      
      For some reason, applying this work-around does not fix the
      "could not split insn" error for that commit,
      while it does work for
      commit 277ba134.
      2e39987f
    • Marko Mäkelä's avatar
      MDEV-26467: Avoid futile spin loops · 277ba134
      Marko Mäkelä authored
      Typically, index_lock and fil_space_t::latch will be held for a longer
      time than the spin loop in latch acquisition would be waiting for.
      Let us avoid spin loops for those as well as dict_sys.latch, which
      could be held in exclusive mode for a longer time (while loading
      metadata into the buffer pool and the dictionary cache).
      
      Performance testing on a dual Intel Xeon E5-2630 v4 (2 NUMA nodes)
      suggests that the buffer pool page latch (block_lock) benefits from a
      spin loop in both read-only and read-write workloads where the working
      set is slightly larger than the buffer pool. Presumably, most contention
      would occur on leaf page latches. Contention on upper level pages in
      the buffer pool should intuitively last longer.
      
      We introduce srw_spin_lock and srw_spin_mutex to allow users of
      srw_lock or srw_mutex to opt in for the spin loop.
      On Microsoft Windows, a spin loop variant was and will not be available;
      srw_mutex and srw_lock will simply wrap SRWLOCK.
      That is, on Microsoft Windows, the parameters innodb_sync_spin_loops
      and innodb_spin_wait_delay will only affect block_lock.
      277ba134
    • Marko Mäkelä's avatar
      MDEV-26467: Avoid re-reading srv_spin_wait_delay inside a loop · 0f0b7e47
      Marko Mäkelä authored
      Invoking ut_delay(srv_wpin_wait_delay) inside a spinloop would
      cause a read of 2 global variables as well as multiplication.
      Let us loop around MY_RELAX_CPU() using a precomputed loop count
      to keep the loops simpler, to help them scale better.
      
      We also tried precomputing the delay into a global variable,
      but that appeared to result in slightly worse throughput.
      0f0b7e47
    • Marko Mäkelä's avatar
      MDEV-26467 Unnecessary compare-and-swap loop in srw_mutex · a73eedbf
      Marko Mäkelä authored
      srw_mutex::wait_and_lock(): In the spin loop, we will try to poll
      for non-conflicting lock word state by reads, avoiding any writes.
      We invoke explicit std::atomic_thread_fence(std::memory_order_acquire)
      before returning. The individual operations on the lock word
      can use memory_order_relaxed.
      
      srw_mutex::lock: Document that the value for a single writer is
      HOLDER+1 instead of HOLDER.
      
      srw_mutex::wr_lock_try(), srw_mutex::wr_unlock(): Adjust the value
      of the lock word of a single writer from HOLDER to HOLDER+1.
      a73eedbf
    • Marko Mäkelä's avatar
      Merge 10.5 into 10.6 · 7730dd39
      Marko Mäkelä authored
      7730dd39
    • Marko Mäkelä's avatar
      MDEV-26547 Restoring InnoDB buffer pool dump is single-threaded for no reason · 84c578c7
      Marko Mäkelä authored
      buf_read_page_background(): Remove the parameter "bool sync"
      and always actually initiate a page read in the background.
      
      buf_load(): Always submit asynchronous reads. This allows
      page checksums to be verified in concurrent threads as
      soon as the reads are completed.
      84c578c7
    • Marko Mäkelä's avatar
      MDEV-26533 fixup: GCC -Wformat · 7d351f1a
      Marko Mäkelä authored
      7d351f1a
    • Nayuta Yanagisawa's avatar
      MDEV-25684 Crash in THD::find_temporary_table while calling spider_direct_sql... · 1fda0544
      Nayuta Yanagisawa authored
      MDEV-25684 Crash in THD::find_temporary_table while calling spider_direct_sql UDF without temporary table created
      
      The server crashed when SPIDER_DIRECT_SQL UDF was called with
      non-existing temporary table.
      
      The bug has been introduced by 91ffdc83. The commit removed
      the check, from THD::open_temporary_table(), which ensure that
      the target temporary tables exist.
      
      We can fix the bug by adding the check before the call of
      THD::open_temporary_table().
      1fda0544
  4. 05 Sep, 2021 4 commits
  5. 04 Sep, 2021 3 commits
  6. 03 Sep, 2021 1 commit
  7. 02 Sep, 2021 2 commits
    • Vladislav Vaintroub's avatar
      Fix create_background_thd() · e38a05e2
      Vladislav Vaintroub authored
      Allow the caller to have current_thd. Also do not store
      PSI_CALL_get_thread() in the new THD, it is a thread local storage variable
      that can become invalid any time, we do not control the lifetime of the
      caller's thread.
      e38a05e2
    • Marko Mäkelä's avatar
      MDEV-24258 fixup: Throttle purge with exclusive dict_sys.latch · 46904424
      Marko Mäkelä authored
      A performance regression was observed after
      commit 82b7c561
      because purge tasks would end up waiting more elsewhere,
      most notably trx_purge_get_next_rec() and trx_purge_truncate_history().
      
      row_purge_parse_undo_rec(): Prevent the performance regression by
      unnecessarily acquiring dict_sys.latch in exclusive mode after the
      table lookup.
      46904424
  8. 01 Sep, 2021 4 commits
  9. 31 Aug, 2021 7 commits
    • Marko Mäkelä's avatar
      241e2ba6
    • Marko Mäkelä's avatar
      Merge 10.5 into 10.6 · 55a344ff
      Marko Mäkelä authored
      55a344ff
    • Marko Mäkelä's avatar
      MDEV-4750 follow-up: Reduce disabling innodb_stats_persistent · 9608773f
      Marko Mäkelä authored
      This essentially reverts commit 4e89ec66
      and only disables InnoDB persistent statistics for tests where it is
      desirable. By design, InnoDB persistent statistics will not be updated
      except by ANALYZE TABLE or by STATS_AUTO_RECALC.
      
      The internal transactions that update persistent InnoDB statistics
      in background tasks (with innodb_stats_auto_recalc=ON) may cause
      nondeterministic query plans or interfere with some tests that deal
      with other InnoDB internals, such as the purge of transaction history.
      9608773f
    • Marko Mäkelä's avatar
      MDEV-25919: Replace dict_table_t::stats_bg_flag with MDL · 45a05fda
      Marko Mäkelä authored
      The purpose of dict_table_t::stats_bg_flag was to prevent
      race conditions between DDL operations and a background thread
      that updates persistent statistics for InnoDB tables.
      
      Now that with the parent commit, we started to acquire a
      shared meta-data lock (MDL) on the InnoDB persistent statistics tables
      in background tasks that access them, we may easily acquire MDL
      on the table for which the statistics are being updated. This will by
      design prevent race conditions with any DDL operations on that table,
      and the stats_bg_flag may be removed.
      
      dict_stats_process_entry_from_recalc_pool(): Complete rewrite.
      During the processing, retain the entry in recalc_pool, so
      that dict_stats_recalc_pool_del() will be able to request
      deletion of the entry, or delete the entry if its caller is
      holding MDL_EXCLUSIVE while we are waiting for MDL.
      
      recalc_pool: In addition to the table ID, store a state for
      inter-thread communication, so that dict_stats_recalc_pool_del()
      can wait until all processing is finished.
      
      Reviewed by: Thirunarayanan Balathandayuthapani
      45a05fda
    • Marko Mäkelä's avatar
      MDEV-25919: Lock tables before acquiring dict_sys.latch · c5fd9aa5
      Marko Mäkelä authored
      In commit 1bd681c8 (MDEV-25506 part 3)
      we introduced a "fake instant timeout" when a transaction would wait
      for a table or record lock while holding dict_sys.latch. This prevented
      a deadlock of the server but could cause bogus errors for operations
      on the InnoDB persistent statistics tables.
      
      A better fix is to ensure that whenever a transaction is being
      executed in the InnoDB internal SQL parser (which will for now
      require dict_sys.latch to be held), it will already have acquired
      all locks that could be required for the execution. So, we will
      acquire the following locks upfront, before acquiring dict_sys.latch:
      
      (1) MDL on the affected user table (acquired by the SQL layer)
      (2) If applicable (not for RENAME TABLE): InnoDB table lock
      (3) If persistent statistics are going to be modified:
      (3.a) MDL_SHARED on mysql.innodb_table_stats, mysql.innodb_index_stats
      (3.b) exclusive table locks on the statistics tables
      (4) Exclusive table locks on the InnoDB data dictionary tables
      (not needed in ANALYZE TABLE and the like)
      
      Note: Acquiring exclusive locks on the statistics tables may cause
      more locking conflicts between concurrent DDL operations.
      Notably, RENAME TABLE will lock the statistics tables
      even if no persistent statistics are enabled for the table.
      
      DROP DATABASE will only acquire locks on statistics tables if
      persistent statistics are enabled for the tables on which the
      SQL layer is invoking ha_innobase::delete_table().
      For any "garbage collection" in innodb_drop_database(), a timeout
      while acquiring locks on the statistics tables will result in any
      statistics not being deleted for any tables that the SQL layer
      did not know about.
      
      If innodb_defragment=ON, information may be written to the statistics
      tables even for tables for which InnoDB persistent statistics are
      disabled. But, DROP TABLE will no longer attempt to delete that
      information if persistent statistics are not enabled for the table.
      
      This change should also fix the hangs related to InnoDB persistent
      statistics and STATS_AUTO_RECALC (MDEV-15020) as well as
      a bug that running ALTER TABLE on the statistics tables
      concurrently with running ALTER TABLE on InnoDB tables could
      cause trouble.
      
      lock_rec_enqueue_waiting(), lock_table_enqueue_waiting():
      Do not issue a fake instant timeout error when the transaction
      is holding dict_sys.latch. Instead, assert that the dict_sys.latch
      is never being held here.
      
      lock_sys_tables(): A new function to acquire exclusive locks on all
      dictionary tables, in case DROP TABLE or similar operation is
      being executed. Locking non-hard-coded tables is optional to avoid
      a crash in row_merge_drop_temp_indexes(). The SYS_VIRTUAL table was
      introduced in MySQL 5.7 and MariaDB Server 10.2. Normally, we require
      all these dictionary tables to exist before executing any DDL, but
      the function row_merge_drop_temp_indexes() is an exception.
      When upgrading from MariaDB Server 10.1 or MySQL 5.6 or earlier,
      the table SYS_VIRTUAL would not exist at this point.
      
      ha_innobase::commit_inplace_alter_table(): Invoke
      log_write_up_to() while not holding dict_sys.latch.
      
      dict_sys_t::remove(), dict_table_close(): No longer try to
      drop index stubs that were left behind by aborted online ADD INDEX.
      Such indexes should be dropped from the InnoDB data dictionary by
      row_merge_drop_indexes() as part of the failed DDL operation.
      Stubs for aborted indexes may only be left behind in the
      data dictionary cache.
      
      dict_stats_fetch_from_ps(): Use a normal read-only transaction.
      
      ha_innobase::delete_table(), ha_innobase::truncate(), fts_lock_table():
      While waiting for purge to stop using the table,
      do not hold dict_sys.latch.
      
      ha_innobase::delete_table(): Implement a work-around for the rollback
      of ALTER TABLE...ADD PARTITION. MDL_EXCLUSIVE would not be held if
      ALTER TABLE hits lock_wait_timeout while trying to upgrade the MDL
      due to a conflicting LOCK TABLES, such as in the first ALTER TABLE
      in the test case of Bug#53676 in parts.partition_special_innodb.
      Therefore, we must explicitly stop purge, because it would not be
      stopped by MDL.
      
      dict_stats_func(), btr_defragment_chunk(): Allocate a THD so that
      we can acquire MDL on the InnoDB persistent statistics tables.
      
      mysqltest_embedded: Invoke ha_pre_shutdown() before free_used_memory()
      in order to avoid ASAN heap-use-after-free related to acquire_thd().
      
      trx_t::dict_operation_lock_mode: Changed the type to bool.
      
      row_mysql_lock_data_dictionary(), row_mysql_unlock_data_dictionary():
      Implemented as macros.
      
      rollback_inplace_alter_table(): Apply an infinite timeout to lock waits.
      
      innodb_thd_increment_pending_ops(): Wrapper for
      thd_increment_pending_ops(). Never attempt async operation for
      InnoDB background threads, such as the trx_t::commit() in
      dict_stats_process_entry_from_recalc_pool().
      
      lock_sys_t::cancel(trx_t*): Make dictionary transactions immune to KILL.
      
      lock_wait(): Make dictionary transactions immune to KILL, and to
      lock wait timeout when waiting for locks on dictionary tables.
      
      parts.partition_special_innodb: Use lock_wait_timeout=0 to instantly
      get ER_LOCK_WAIT_TIMEOUT.
      
      main.mdl: Filter out MDL on InnoDB persistent statistics tables
      
      Reviewed by: Thirunarayanan Balathandayuthapani
      c5fd9aa5
    • Marko Mäkelä's avatar
      MDEV-25919 preparation: Various cleanup · 094de717
      Marko Mäkelä authored
      que_eval_sql(): Remove the parameter lock_dict. The only caller
      with lock_dict=true was dict_stats_exec_sql(), which will now
      explicitly invoke dict_sys.lock() and dict_sys.unlock() by itself.
      
      row_import_cleanup(): Do not unnecessarily lock the dictionary.
      Concurrent access to the table during ALTER TABLE...IMPORT TABLESPACE
      is prevented by MDL and the fact that there cannot exist any
      undo log or change buffer records that would refer to the table
      or tablespace.
      
      row_import_for_mysql(): Do not unnecessarily lock the dictionary
      while accessing fil_system. Thanks to MDL_EXCLUSIVE that was acquired
      by the SQL layer, only one IMPORT may be in effect for the table name.
      
      row_quiesce_set_state(): Do not unnecessarily lock the dictionary.
      The dict_table_t::quiesce state is documented to be protected by
      all index latches, which we are acquiring.
      
      dict_table_close(): Introduce a simpler variant with fewer parameters.
      
      dict_table_close(): Reduce the amount of calls.
      We can simply invoke dict_table_t::release() on startup or
      in DDL operations, or when the table is inaccessible.
      In none of these cases, there is no need to invalidate the
      InnoDB persistent statistics.
      
      pars_info_t::graph_owns_us: Remove (unused).
      
      pars_info_free(): Define inline.
      
      fts_delete(), trx_t::evict_table(), row_prebuilt_free(),
      row_rename_table_for_mysql(): Simplify.
      
      row_mysql_lock_data_dictionary(): Remove some references;
      use dict_sys.lock() and dict_sys.unlock() instead.
      
      row_mysql_lock_table(): Remove. Use lock_table_for_trx() instead.
      
      ha_innobase::check_if_supported_inplace_alter(),
      row_create_table_for_mysql(): Simply assert dict_sys.sys_tables_exist().
      In commit 49e2c8f0 and
      commit 1bd681c8 srv_start()
      actually guarantees that the system tables will exist,
      or the server is in read-only mode, or startup will fail.
      
      Reviewed by: Thirunarayanan Balathandayuthapani
      094de717
    • Marko Mäkelä's avatar
      MDEV-19505 Do not hold mutex while calling que_graph_free() · 6a2cd6f4
      Marko Mäkelä authored
      sym_tab_free_private(): Do not call dict_table_close(), but
      simply invoke dict_table_t::release(), which we can do without
      locking the whole dictionary cache. (Note: On user tables it
      may still be necessary to invoke dict_table_close(), so that
      InnoDB persistent statistics will be deinitialized as expected.)
      
      fts_check_corrupt(), row_fts_merge_insert(): Invoke
      aux_table->release() to simplify the code. This is never a user table.
      
      fts_que_graph_free(), fts_que_graph_free_check_lock(): Replaced with
      que_graph_free().
      
      Reviewed by: Thirunarayanan Balathandayuthapani
      6a2cd6f4