MySQL 性能优化5.7 Innodb事务系统(4)

thread_pool(线程池),是指mysql 创建若干工作线程来共同处理所有连接的用户请求,用户的请求的方式不再是 ‘one thread per connection’,而是多个线程共同接收并处理多个连接的请求,在数据库的底层处理方面(mysql_execute_command),单线程的处理方式和线程池的处理方式是一致的。


thread_pool 的工作原理

启动 thread_pool 的mysql 会创建thread_pool_size 个thread group , 一个timer thread, 每个thread group 最多拥有thread_pool_oversubscribe个活动线程,一个listener线程,listener线程负责监听分配到thread group中的连接,并将监听到的事件放入到一个queue中,worker线程从queue中取出连接的事件并执行具体的操作,执行的过程和one thread per connection 相同。timer threaad 则是为了监听各个threadgroup的运行情况,并根据是否阴塞来创建新的worker线程。

thread_pool 建立连接的堆栈如下:

mysqld_main handle_connections_sockets create_new_thread tp_add_connection queue_put

thread group中的 worker 处理请求的堆栈如下:

0 mysql_execute_command

1 0x0000000000936f40 in mysql_parse

2 0x0000000000920664 in dispatch_command

3 0x000000000091e951 in do_command

4 0x0000000000a78533 in threadpool_process_request

5 0x000000000066a10b in handle_event

6 0x000000000066a436 in worker_main

7 0x0000003562e07851 in start_thread ()

8 0x0000003562ae767d in clone ()

其中worker_main函数是woker线程的主函数,调用mysql本身的do_command 进行消息解析及处理,和one_thread_per_connection 是一样的逻辑; thread_pool 自行控制工作的线程个数,进而实现线程的管理。


thread_pool中线程的创建:

1. listener线程将监听事件放入mysql放入queue中时,如果发现当前thread group中的活跃线程数active_thread_count为零,则创建新的worker 线程;

2. 正在执行的线程阻塞时,如果发现当前thread group中的活跃线程数active_thread_count为零,则创建新的worker 线程;

3. timer线程在检测时发现没有listener线程且自上次检测以来没有新的请求时会创建新的worker线程,其中检测的时间受参数threadpool_stall_limit控制;

4. timer线程在检测时发现没有执行过新的请求且执行队列queue 不为空时会创建新的worker线程;


worker线程的伪码如下:

worker_main { while(connection) { connection= get_event(); /* get_event函数用于从该线程所属thread_Group中取得事件,然后交给Handle_event函数处理,在同一Group内部,只有thread_pool_oversubscribe个线程能同时工作,多余的线程会进入sleep状态 */ if(connection) handle_event(connection); /* 如果是没有登录过的请求,则进行授权检查,并将其Socket绑定到thread_group中的pollfd中,并设置Connection到event中的指针上;对于登录过的,直接处理请求 */ } // 线程销毁 }


thread_pool中线程的销毁:

当从队列queue中取出的connection为空时,则此线程销毁,取connection所等待的时间受参数thread_pool_idle_timeout的控制; 综上,thread_pool通过线程的创建及销毁来自动处理worker的线程个数,在负载较高时,创建的线程数目较高,负载较低时,会销毁多余的worker线程,从而降低连接个数带来的影响的同时,提升稳定性及性能。同时,threadpool中引入了Timer 线程,主要做两个事情。

1. 定期检查每个thread_group是否阻塞,如果阻塞,则进行唤醒或创建线程的工作;

2. 检查每个thread_group中的连接是否超时,如果超时则关掉连接并释放相应的资源;


threadpool在使用中存在的问题:

1. 由于threadpool严格控制活跃线程数的限制,如果同时有多个大查询同时分配到了同一个thread group,则会造成此group中的请求过慢,rt 升高,最典型的就是多个binlog dump 线程同时分配到了同一个group内;

2. 开启了事务模式时,非事务模式的请求会放入低优先级队列,因此可能在较长时间内得不到有效处理,极端情况下,会导致实例hang 住,例如某个连接执行了 flush tables with read lock ,并且此连接的后续请求都会放入低优先级,那么有可能会造成实列hang住;

3. 较小并发下,threadpool 性能退化的问题;

MySQL· 性能优化·并行复制外建约束问题

背景:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/32aa798820a73ae0b8e4bf467d6c5acb.html