1、问题的根源最近在查看某数据库的性能时,通过top-Humysql看到了一个很奇怪的现象。线程有自己的名称。开始以为是哪个版本是厂家维护的,如下:PIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND8146mysql200416472073454026624S0.09.90:00.96mysqld8159mysql2004164720S90.04736654:00.02ib_io_ibuf8160mysql200416472073454026624S0.09.90:00.02ib_io_log8161mysql200416472073454026624S0.00.09.98162mysql200416472073454026624S0.09.90:00.03ib_io_rd-2...后来装了个8.0.28,发现果然是正式版的新玩意儿。虽然能猜到一些线程的作用,但是还是很陌生Look,因为这个名字和performance_schema.thread中的名字不一样。下面我们就来看看它的做法和对应关系。然而,这一小步对于DBA来说是一大步。我们以前看Oracle进程的时候,习惯于命名进程名。这样做的好处是我们可以直接从OS层面判断是哪个函数受到了压力。增加。2、以往对应的方法我们知道,在获取到线程的LWP号后,需要通过lwp和thread_os_id的对应,去performance_schema.thread中,得到如下结果:PIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+命令5524MYSQL200405258879240011676S0.027.40:03.82MySQLD5533MySQL200405258879240011676S0.027.40:00.00.00.00.00.00.00.00.00MySQLD55556MYSSQL200405252525252525252525252559L2004.YYSESQL200477.LESSQL2004.YN4049.LESSQL2004.YN4049.LESSQL2004.YN4049.LESSQL2004.YN4049.RESSQL2004.YN4049.LYYESSQL时405258879240011676S0.027.40:00.00mysqld...---------------------------------------+-------------+|姓名|thread_os_id|+----------------------------------------+--------------+|线程/sql/主|5524||线程/sql/thread_timer_notifier|5533||线程/innodb/io_ibuf_thread|5556||线程/innodb/io_read_thread|5558||线程/innodb/io_log_thread|5557|...如果某个线程的CPU或者IO很高,我们就可以知道是什么线程了。当然你也可以加入information_schema.processlist来获取进程id、状态等有用的信息。3、简单实现方法的讨论比如以innodb为例,将所有线程的OS线程名放在一个数组all_innodb_threads中,其中每个元素都是一个结构体,其中包含了我们OS线程名的元素。代码注释很多,我放一些通俗易懂的:typedefstructPSI_thread_info_v5PSI_thread_info;向操作系统公布的线程名称。此功能是可选的,可提高支持pthread_setname_np()风格的平台的可观察性。这里我们也看到需要支持pthread_setname_np函数。当调用register_thread_class注册所有类时,这些OS线程名会被放在一个名为thread_class_array的全局内存中,这样在创建线程时,应该可以很方便的从全局内存中获取到每个线程的OS线程名(的当然我没有去仔细看看)。那么在创建线程的时候,我们调用my_thread_self_setname来设置OS线程名,其实就是调用pthread_setname_np。4.新的LinuxOS线程名称与performance_schema.threads中名称的对应关系为了快速获取对应的方法,我添加了一些输出内容,这样只要启动一个线程,就会打印到错误日志中,因为如果你一个一个地去每个线程启动时带入的OS线程名,消耗起来太慢了。结果如下:catmysql3380.err|grep-w'initthreads'[initthreads]osname:boot--mysqlname:thread/sql/bootstrap[initthreads]osname:ib_io_ibuf--mysqlname:thread/innodb/io_ibuf_thread[initthreads]osname:ib_io_log--mysqlname:thread/innodb/io_log_thread[initthreads]osname:ib_io_rd-1--mysqlname:thread/innodb/io_read_thread[initthreads]osname:ib_io_rd-2--mysql名称:thread/innodb/io_read_thread[初始化线程]os名称:ib_io_rd-3--mysql名称:thread/innodb/io_read_thread[初始化线程]os名称:ib_io_rd-4--mysql名称:thread/innodb/io_read_thread[initthreads]osname:ib_io_rd-5--mysqlname:thread/innodb/io_read_thread[initthreads]osname:ib_io_rd-6--mysqlname:thread/innodb/io_read_thread[initthreads]osname:ib_io_rd-7--mysql名称:thread/innodb/io_read_th读取[initthreads]osname:ib_io_rd-8--mysqlname:thread/innodb/io_read_thread[initthreads]osname:ib_io_wr-1--mysqlname:thread/innodb/io_write_thread[initthreads]osname:ib_io_wr-2--mysql名称:thread/innodb/io_write_thread[初始化线程]os名称:ib_io_wr-3--mysql名称:thread/innodb/io_write_thread[初始化线程]os名称:ib_io_wr-4--mysql名称:thread/innodb/io_write_thread[初始化线程]操作系统名称:ib_pg_flush_co--mysql名称:thread/innodb/page_flush_coordinator_thread[初始化线程]操作系统名称:ib_pg_flush-1--mysql名称:thread/innodb/page_flush_thread[初始化线程]操作系统名称:ib_pg_flush-2--mysqlname:thread/innodb/page_flush_thread[initthreads]osname:ib_pg_flush-3--mysqlname:thread/innodb/page_flush_thread[initthreads]osname:ib_recv_write--mysqlname:thread/innodb/recv_writer_thread[init线程]osname:ib_log_checkpt--mysqlname:thread/innodb/log_checkpointer_thread[初始化线程]osname:ib_log_fl_notif--mysql名称:线程/innodb/log_flush_notifier_thread[初始化线程]]osname:ib_log_writer--mysqlname:thread/innodb/log_writer_thread[initthreads]osname:ib_par_rseg-0--mysqlname:thread/innodb/parallel_rseg_init_thread[initthreads]osname:ib_par_rseg-0--mysqlname:thread/innodb/parallel_rseg_init_thread[initthreads]osname:ib_srv_lock_to--mysqlname:thread/innodb/srv_lock_timeout_thread[initthreads]osname:ib_srv_err_mon--mysqlname:thread/innodb/srv_error_monitor_thread[initthreads]osname:ib_srv_mon--mysqlname:thread/innodb/srv_monitor_thread[initthreads]osname:ib_buf_resize--mysqlname:thread/innodb/buf_resize_thread[initthreads]osname:ib_src_main--mysqlname:thread/innodb/srv_master_thread[initthreads]os姓名:我b_dict_stats--mysqlname:thread/innodb/dict_stats_thread[初始化线程]osname:ib_fts_opt--mysqlname:thread/innodb/fts_optimize_thread[初始化线程]osname:xpl_worker-1--mysqlname:thread/mysqlx/worker[初始化线程]操作系统名称:xpl_worker-2--mysql名称:thread/mysqlx/worker[初始化线程]操作系统名称:xpl_accept-1--mysql名称:thread/mysqlx/acceptor_network[初始化线程]操作系统名称:ib_buf_dump--mysql名称:thread/innodb/buf_dump_thread[initthreads]osname:ib_clone_gtid--mysqlname:thread/innodb/clone_gtid_thread[initthreads]osname:ib_srv_purge--mysqlname:thread/innodb/srv_purge_thread[initthreads]操作系统名称:ib_srv_wkr-1--mysql名称:线程/innodb/srv_worker_thread[初始化线程]操作系统名称:ib_srv_wkr-2--mysql名称:线程/innodb/srv_worker_thread[初始化线程]操作系统名称:ib_srv_wkr-3--mysql名称:线程/innodb/srv_worker_thread[initthreads]osname:sig_handler--mysqlname:thread/sql/signal_handler[initthreads]osname:xpl_accept-2--mysqlname:thread/mysqlx/acceptor_network[初始化线程]osname:xpl_accept-3--mysqlname:thread/mysqlx/acceptor_network[initthreads]osname:gtid_zip--mysqlname:thread/sql/compress_gtid_table[initthreads]osname:connection--mysqlname:thread/sql/one_connection可以看到创建了很多线程,不过我们获取它们的对应关系就足够了。这里我们不对每个线程一一讨论。功能,但我们对其中的大部分都非常熟悉,比如purgethread/cleanerthread,我将在这里列出其中的一些,其他的你自己看看。purge线程srv_purge_thread主要用于清除delete标志,释放undo表空间;cleanthreadpage_cleaner_threadDBWR主要用于清理磁盘脏数据和管理LRU链表;异步IO线程io_read_thread/io_write_thread通常用于数据预读和脏清洗异步AIO,用于合并可能的hashIO,提高连续IO的性能;字典收集线程dict_stats_thread会在数据修改10%后触发收集统计;锁超时监控线程srv_lock_timeout_thread用于监控innodb行锁超时,超时进行事务回滚;GTID压缩线程compress_gtid_table将历史gtid压缩到一个范围内,防止gtid_executed表过长。slaveio线程slave_io从library的DUMP线程接收binlogevents。将这些事件写入中继日志;slavedumpthread是前台线程主库监听binlog变化,并发送binlogEventsslavesql线程slave_sql负责执行从库的binlogevents;userthreadone_connection一个会话就是一个用户线程,对于用户线程Word。可以通过processlist_id和showprocesslist来监控线程;srv_error_monitor_thread所谓的信号量监控线程,注意这个信号量不是OS信号量。就是Innodb内部的rwlock和mutex;当参数innodb_status_output打开时,srv_monitor_thread线程每15秒输出一个showengineinnodbstatus信息到日志文件。也会自动开启。比如Innodb,如果内存不足会自动开启。log_writer线程:将redo写入redo文件;log_write_notifier线程:通知用户session写入redo文件结束;log_flusher线程:重做fsync到重做文件;log_flush_notifier线程:通知用户sessionfsync结束;log_checkpointer线程:定期检查脏数据写入磁盘的重做位置。5.使用pthread_setname_np命名线程这里我只是写了4个循环线程调用这个函数来命名我的线程D-GPWK,这对CPU消耗比较大。结果如下:image.png如果这个线程是MySQL的线程。当我们看到这个结果时,我们就可以了解大致的方向。《MySQL主从原理》作者:高鹏(八怪)
