mysql8.0.20 Innodb引擎共有34种线程(具体可参考ha_innodb.cc的全局线程组all_innodb_threads),分别为
- master线程 (srv_master_thread)
- Error monitor线程 (srv_error_monitor_thread)
- Monitor线程 (srv_monitor_thread)
- redo log closed线程 (log_closer)
- checkpointer线程 (log_checkpointer)
- redo write线程 (log_writer)
- redo flush线程 (log_flusher)
- redo write 通知线程 (log_write_notifier)
- redo flush 通知线程 (log_flush_notifier)
- bp dump线程 (buf_dump_thread)
- bp resize线程 (buf_resize_thread)
- 表信息统计计算线程 dict_stats_thread
- 锁监控线程 lock_wait_timeout_thread
- alter表空间加解密回滚线程 fsp_init_resume_alter_encrypt_tablespace srv_ts_alter_encrypt_thread
- 奔溃恢复事务回滚线程 trx_recovery_rollback_thread
- 通知刷脏线程 recv_writer_thread
- purge协调线程 srv_purge_coordinator_thread
- purge工作线程组 srv_worker_thread
- 刷脏工作协调线程 buf_flush_page_coordinator_thread
- 刷脏工作线程组 buf_flush_page_cleaner_thread
- 日志归档线程 log_archiver_thread
- 写redo log归档线程 meb::redo_log_archive_consumer_thread
- 内存page归档线程 page_archiver_thread
- gtid持久化线程 clone_gtid_thread
- 全文索引优化线程 fts_optimize_thread
- 并行merge线程 fts_parallel_merge_thread
- 并行tokenization线程 fts_parallel_tokenization_thread
- io_ibuf_thread
- io_log_thread
- io_read_thread
- io_write_thread
- 并行查询生成者线程 parallel_read_thread
- 并行查询消费者线程 parallel_read_ahead_thread
- clone_ddl_thread 暂时未用到
具体分为分为下面几大类:
1 主线程 master
Master thread优先级最高, 其内部包含几个循环:主循环(loop)、后台循环(background loop)、暂停循环(suspend loop).master thread会根据其内部运行的相关状态在前述各循环间中进行切换.大部分操作在主循环(loop)中完成,Innodb1.2.X后都是1s循环,不在有10s循环:
- 1s操作分活跃、空闲两种操作,这两种操作主要包括:
- 日志缓冲刷新到磁盘(必做) 即使某个事务还没有提交,InnoDB仍然每秒会将redo log缓冲中的内容刷新到文件。这可以很好地解释为什么再大的事务提交(commit)的时间也是很短的,具体操作可参考函数log_free_check
- 惰性删除表(可能) 当alter table请求发生在unix上,当表上没有查询请求时可删除表信息,参考函数srv_master_do_active_tasks
- 合并change buffer(可能),参考函数ibuf_merge_in_background
- 清除table中无用的的表(可能) srv_master_evict_from_table_cache
上面三种可能的操作在mysql8.0.20中,活跃操作对应处理函数为srv_master_do_active_tasks、空闲操作对应函数srv_master_do_idle_tasks。
2 监控线程
- Monitor线程(m_monitor) 5s loop循环,每隔15s打印Innodb各种监控信息(若配置)
- Error monitor线程 (m_error_monitor)错误、告警监控线程
3 Redo log 相关线程
- redo log closed线程 (m_log_closer)
- checkpointer线程 (m_log_checkpointer)
- redo write线程 (m_log_writer)
- redo flush线程 (m_log_flusher)
- redo write 通知线程 (m_log_write_notifier)
- redo flush 通知线程 (m_log_flush_notifier)
4 buf pool相关线程
- bp dump线程 (buf_dump_thread)用户线程触发bp内存数据导入导出,在ddl recover完成后才启动该线程,参考函数srv_start_threads_after_ddl_recovery
- bp resize线程 buf_resize_thread 用户线程触发resize bp,修改bp大小
5 表信息统计线程
表信息统计计算线程(m_dict_stats) 用于重新计算表或索引的统计信息,在一个loop中,等待事件dict_stats_event,或者每隔10秒被无条件唤醒。实际工作函数为dict_stats_process_entry_from_recalc_pool(),涉及全局变量dict_sys、及表操作
6 锁相关线程
mysql锁监控线程 lock_wait_timeout_thread
7 奔溃恢复临时线程
- alter表空间加解密回滚线程 (fsp_init_resume_alter_encrypt_tablespace)在ddl奔溃恢复完成后启动,执行完成退出
- 奔溃恢复事务回滚线程 (m_trx_recovery_rollback)
- 通知刷脏线程(m_recv_writer) 和page cleaner线程配合使用,它会去通知page cleaner线程去flush崩溃恢复产生的脏页,直到recv_sys中存储的redo记录都被应用完成并彻底释放掉(recv_sys->heap == NULL)
8 purge相关线程
DDL恢复完成后启动,参考函数srv_start_threads_after_ddl_recovery
- purge协调线程(srv_purge_coordinator_thread)
- purge工作线程组 (srv_worker_thread)
9 page clean相关线程
page clean线程分为下面两种:
- 刷脏协调线程(buf_flush_page_coordinator_thread)
- 刷脏工作线程组 (buf_flush_page_cleaner_thread)
buf_flush_page_coordinator_thread协调线程的主循环主线程以最多1s的间隔或者收到buf_flush_event事件就会触发进行一轮的刷脏。刷脏方式分三种,同步刷脏、活跃刷脏和空闲刷脏,其中空闲刷脏只有协调线程进行刷脏操作,不会唤醒work线程。
协调线程非空闲刷脏,首先会调用pc_request()函数,这个函数的作用就是为每个slot代表的缓冲池实例计算要刷脏多少页,然后把每个slot的state设置PAGE_CLEANER_STATE_REQUESTED, 唤醒等待的工作线程。由于协调线程也会和工作线程一样做具体的刷脏操作,所以它在唤醒工作线程之后,会调用pc_flush_slot(),和其它的工作线程并行去做刷脏页操作。一但它做完自己的刷脏操作,就会调用pc_wait_finished()等待所有的工作线程完成刷脏操作。完成这一轮的刷脏之后,协调线程会收集一些统计信息,比如这轮刷脏所用的时间,以及对LRU和flush_list队列刷脏的页数等。然后会根据当前的负载计算应该sleep的时间、以及下次刷脏的页数,为下一轮的刷脏做准备。
10 mysql clone相关线程
- 日志归档线程(m_log_archiver) 归档有效的redo 日志,与redo_log_archive_consumer用于redo log 归档功能 , MySQL8.0.17中引入了redo log的归档功能,如果开启归档功能,redo log会持续不断的生成,而不会覆盖掉之前的redo log
- 写redo log归档线程 redo_log_archive_consumer
- 内存page归档线程 (m_page_archiver)
11 GTID持久化线程 (m_gtid_persister)
在ddl recover完成后启动,参考函数srv_start_threads_after_ddl_recovery,进行gtid持久化操作
12 全文索引相关线程
- 全文索引优化线程 (m_fts_optimize) 读取队列fts_optimize_wq消息,对全文索引表进行优化
- 并行merge线程 fts_parallel_merge_thread,创建索引若存在全文索引时会调用执行
- 并行tokenization线程 fts_parallel_tokenization_thread 全文的读取或排序时会执行调用
13 IO 线程
- io_ibuf_thread change buffer thread负责把改变缓冲(change buffer)中的内容刷新到磁盘
- io_log_thread redo log thread负责把日志缓冲中的内容刷新到redo log文件中
- io_read_thread read thread为mysql的读线程,默认为4个,其负责将数据页从磁盘上读入,其由innodb_read_io_threads选项控制.用户线程发起读请求并将其放至读请求队列,read threads从读请求队列获取读任务并完成.
- io_write_thread write thread为mysql的写线程,默认为4个,其负责将数据页从缓冲区写出到磁盘,其由innodb_write_io_threads控制选项控制.page_cleaner线程发起写请求并将其放至写请求队列,write threads从写请求队列获取写任务并完成.
14 并行查询线程
- 并行查询生成者线程 parallel_read_thread
- 并行查询消费者线程 parallel_read_ahead_thread