MySQL truncate慢影响系统qps分析

来源:这里教程网 时间:2026-03-01 16:46:56 作者:

bug:文中提到在8.0修复,下面看下5.7版本的调用堆栈

mysqld!buf_LRU_flush_or_remove_pages(unsigned long, buf_remove_t, trx_t const*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0lru.cc:938)
mysqld!fil_reinit_space_header_for_table(dict_table_t*, unsigned long, trx_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/fil/fil0fil.cc:3016)
mysqld!row_truncate_table_for_mysql(dict_table_t*, trx_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0trunc.cc:2085)
mysqld!ha_innobase::truncate() (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/handler/ha_innodb.cc:12477)
mysqld!handler::ha_truncate() (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/handler.cc:4730)
mysqld!Sql_cmd_truncate_table::handler_truncate(THD*, TABLE_LIST*, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_truncate.cc:251)
mysqld!Sql_cmd_truncate_table::truncate_table(THD*, TABLE_LIST*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_truncate.cc:509)
mysqld!Sql_cmd_truncate_table::execute(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_truncate.cc:565)
mysqld!mysql_execute_command(THD*, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:4845)
mysqld!mysql_parse(THD*, Parser_state*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:5584)
mysqld!dispatch_command(THD*, COM_DATA const*, enum_server_command) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1491)
mysqld!do_command(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1032)
mysqld!::handle_connection(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/conn_handler/connection_handler_per_thread.cc:313)
mysqld!::pfs_spawn_thread(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/perfschema/pfs.cc:2197)
libsystem_pthread.dylib!_pthread_start (Unknown Source:0)
libsystem_pthread.dylib!thread_start (Unknown Source:0)

fil_reinit_space_header_for_table 是使用相同的space id 重新初始化表空间头在函数中会有

/* Lock the search latch in shared mode to prevent user
    from disabling AHI during the scan */
btr_search_s_lock_all();
DEBUG_SYNC_C("simulate_buffer_pool_scan");
buf_LRU_flush_or_remove_pages(id, BUF_REMOVE_ALL_NO_WRITE, 0);
btr_search_s_unlock_all();

会将btr_search_latch 设置s锁,这样会影响dml

/** Lock all search latches in shared mode. */
UNIV_INLINE
void
btr_search_s_lock_all()
{
for (ulint i = 0; i < btr_ahi_parts; ++i) {
rw_lock_s_lock(btr_search_latches[i]);
}
}

buf_LRU_flush_or_remove_pages(id, BUF_REMOVE_ALL_NO_WRITE, 0);在buf_LRU_flush_or_remove_pages中会遍历每个buffer pool instance,去remove 脏页 所以在执行truncate的时候,尽可能用drop+recreate的方式 drop 的时候会遍历buffer pool 加buffer pool mutex 删除属于这个表的buffer堆栈

mysqld!buf_flush_or_remove_pages(buf_pool_t*, unsigned long, FlushObserver*, bool, trx_t const*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0lru.cc:599)
mysqld!buf_flush_dirty_pages(buf_pool_t*, unsigned long, FlushObserver*, bool, trx_t const*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0lru.cc:700)
mysqld!buf_LRU_remove_pages(buf_pool_t*, unsigned long, buf_remove_t, trx_t const*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0lru.cc:902)
mysqld!buf_LRU_flush_or_remove_pages(unsigned long, buf_remove_t, trx_t const*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0lru.cc:938)
mysqld!fil_delete_tablespace(unsigned long, buf_remove_t) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/fil/fil0fil.cc:2810)
mysqld!row_drop_single_table_tablespace(unsigned long, char const*, char const*, bool, bool, trx_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0mysql.cc:4249)
mysqld!row_drop_table_for_mysql(char const*, trx_t*, bool, bool, dict_table_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0mysql.cc:4800)
mysqld!ha_innobase::delete_table(char const*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/handler/ha_innodb.cc:12595)
mysqld!handler::ha_delete_table(char const*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/handler.cc:4972)
mysqld!ha_delete_table(THD*, handlerton*, char const*, char const*, char const*, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/handler.cc:2601)
mysqld!mysql_rm_table_no_locks(THD*, TABLE_LIST*, bool, bool, bool, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_table.cc:2552)
mysqld!mysql_rm_table(THD*, TABLE_LIST*, char, char) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_table.cc:2202)
mysqld!mysql_execute_command(THD*, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:3628)
mysqld!mysql_parse(THD*, Parser_state*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:5584)
mysqld!dispatch_command(THD*, COM_DATA const*, enum_server_command) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1491)
mysqld!do_command(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1032)
mysqld!::handle_connection(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/conn_handler/connection_handler_per_thread.cc:313)
mysqld!::pfs_spawn_thread(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/perfschema/pfs.cc:2197)
libsystem_pthread.dylib!_pthread_start (Unknown Source:0)
libsystem_pthread.dylib!thread_start (Unknown Source:0)

drop删除的是dirty page,discarding tablespace 会删除lru 中的buffer,lru 中的buffer会用冷热算法自动淘汰,在flush 1024个页后会释放flush mutex,share pool mutex所以在drop的时候,我们关心是否会有问题,可以查看下这个表的最后一次update的时间,感觉这个不太准,还有别的方法? percona 的lazy drop,是做了标记,删除的lru list

The main function that is responsible for cleaning the bufferpool in the event of drop table is  buf_LRU_mark_space_was_deleted(space_id), here  space_id is the id of the tablespace corresponding to the table being dropped. Following are the steps performed in this function:

  • Take a mutex on the LRU list of the buffer pool
  • Scan through the LRU list and for each page in the LRU list:
  • If the page belongs to the tablespace being dropped, then set a flag in the page structure marking the page as belonging to a tablespace being dropped
  • Exit the mutex on the LRU list
  • Take a reader-writer shared lock on the latch protecting the Adaptive Hash Index (AHI)
  • Scan the buffer pool and for each page in the buffer pool
  • If the page has a hash index built on it, (meaning the AHI has an entry for this page):
  • Release the shared lock on the latch protecting the AHI
  • Lock the page in exclusive mode
  • Remove all entries in the AHI pointing to the page
  • Release the lock on the page
  • Take the reader-writer shared lock on the latch protecting the AHI again
  • Release the shared lock on the latch protecting the AHI

    有兴趣学习源码的加群一起学习啊 QQ:    700072075

  • 相关推荐