MySQL8 show processlist 优化

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

he new SHOW PROCESSLIST executes an internal query of a new table,  peformance_schema.processlist , rather than iterate across threads in the thread manager. 8.0之前版本的show processlist 数据是在thread manager 那里获取,会获取一个全局的mutex,8.0后版本的使用新的方式直接使用非阻塞读取表。 下面看下8.0之前的show processlist获取mutex的方法,在mysql_execute_command中有处理该语句的分支

case SQLCOM_SHOW_PROCESSLIST:
if (!thd->security_context()->priv_user().str[0] &&
check_global_access(thd,PROCESS_ACL))
break;
mysqld_list_processes(
thd,
(thd->security_context()->check_access(PROCESS_ACL) ?
NullS :
thd->security_context()->priv_user().str),
lex->verbose);
break;

在获取全部thread的时候,可以看见加了几个mutex,

LOCK_thd_list 在拷贝线程列表的时候使用
void Global_THD_manager::do_for_all_thd_copy(Do_THD_Impl *func)
{
Do_THD doit(func);
mysql_mutex_lock(&LOCK_thd_remove);
mysql_mutex_lock(&LOCK_thd_list);
  /* Take copy of global_thread_list. */
THD_array thd_list_copy(thd_list);
  /*
    Allow inserts to global_thread_list. Newly added thd
    will not be accounted for when executing func.
  */
mysql_mutex_unlock(&LOCK_thd_list);
  /* Execute func for all existing threads. */
std::for_each(thd_list_copy.begin(), thd_list_copy.end(), doit);
DEBUG_SYNC_C("inside_do_for_all_thd_copy");
mysql_mutex_unlock(&LOCK_thd_remove);
}

对应的堆栈如下:

mysqld!Global_THD_manager::do_for_all_thd_copy(Do_THD_Impl*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/mysqld_thd_manager.cc:257)
mysqld!mysqld_list_processes(THD*, char const*, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_show.cc:2390)
mysqld!mysql_execute_command(THD*, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:3643)
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)

LOCK_thd_list 这个mutex 保护线程id集合,所有的线程操作都需要这个mutex,所以你执行show processlist会影响到线程的创建,消除。
导致系统qps 下降,应用连接缓慢。
void Global_THD_manager::add_thd(THD *thd)
{
DBUG_PRINT("info", ("Global_THD_manager::add_thd %p", thd));
  // Should have an assigned ID before adding to the list.
DBUG_ASSERT(thd->thread_id() != reserved_thread_id);
mysql_mutex_lock(&LOCK_thd_list);
  // Technically it is not supported to compare pointers, but it works.
std::pair<THD_array::iterator, bool> insert_result=
thd_list.insert_unique(thd);
if (insert_result.second)
{
++global_thd_count;
}
  // Adding the same THD twice is an error.
DBUG_ASSERT(insert_result.second);
mysql_mutex_unlock(&LOCK_thd_list);
}

8.0通过直接查询表的方式避免这个问题,但是默认是没有开启的,需要设置performance_schema_show_processlist 这个变量开启,不知道为什么默认没有开。 btw,8.0解决了太多的问题,也引发了太多问题。

相关推荐