MySQL 5.6 Threadpool(优先队列)介绍及性能测试【转】
本文来自:http://www.gpfeng.com/?p=540&utm_source=tuicool&utm_medium=referral
背景介绍
MySQL常用(目前线上使用)的线程调度方式是one-thread-per-connection(每连接一个线程),server为每一个连接创建一个线程来服务,连接断开后,这个线程进入thread_cache或者直接退出(取决于thread_cache设置及系统当前已经cache的线程数目),one-thread-per-connection调度的好处是实现简单,而且能够在系统没有遇到瓶颈之前保证较小的响应时间,比较适合活跃的长连接的应用场景,而在大量短连接或者高并发情况下,one-thread-per-connection需要创建/调度大量的线程,产生较高的的context-switch代价,从而使得系统性能下降
为了解决这个问题,Oracle和MariaDB分别推出了threadpool方案,目前Oracle的threadpool实现为plugin方式,并且只添加到在Enterprise版本中,没有公布代码,MariaDB threadpool在5.5版本中引入,我们一直密切关注社区动态并在第一时间测试了MariaDB threapool性能,并且发现了一些其中的问题,比如:要像发挥线程池的优势,需要尽量控制线程池中线程数目,否则会退化成one-thread-per-connection,而如果严格控制线程池中线程数据,可能会出现调度上的死锁,percona在移植MariaDB threadpool的实现后进一步优化了线程池性能,通过引入优先队列很好解决了这个问题,经测试效果明显,因此我们将这个特性port到了AliMySQL中
实现简介
1. threadpool中worker线程处理单位为一个sql,而不是one-thread-per-connection对应的一个连接;当worker线程处理完A连接发送来的一个sql后,A连接没有立刻发送第二条sql,worker线程会去服务其它连接发送来的sql,因此worker线程工作效率更高,系统需要的线程数也更少
2. threadpool本质上是一个生产者-消费者模型,为了减小竞争,threadpool被划分为N个group(n默认为cpu核心数),连接发送的sql根据连接id分配到不同的group中,因此,同一个连接发送的所有sql是被同一个group中的worker线程处理的
3. 每个group都有2个任务队列,即优先队列和普通队列,如果一个sql所在的事务已经开启,则将任务放到优先队列中,否则放到普通队列中,worker线程优先从优先队列中取任务执行,当优先队列为空则从普通队列取任务执行,这个可以保证已经开启的事务优先得到执行,从而尽早释放其占用的资源(主要是锁),可以有效减小响应时间,并且避免调度上的死锁(A和B被分到不同的group中,A事务已经开启,并且获得了锁,可能无法立即得到调度执行,B事务依赖A事务释放锁资源,但是先于A得到调度)
4. 每个group中每个worker线程地位一样,如果遇到任务队列为空的情况,线程会调用epoll_wait批量取任务
5. threadpool额外创建了一个timer线程,每隔一段时间检查一遍所有的group,如果发现group出现异常(堵塞/超时/worker线程数目不够),及时唤醒线程
关于MySQL线程调度接口以及MariaDB threadpool实现细节可以参考之前我写的两篇博客:mysql thread sheduler 源码分析,mariadb 5.5 threadpool 源码分析
threadpool相关参数
root@(none) 05:33:27>show global variables like '%thread_pool%'; |
thread_pool_high_prio_mode
有三个取值:transactions / statements / none
transactions(default): 使用优先队列和普通队列,对于事务已经开启的statement,放到优先队列中,否则放到普通队列中
statements:只使用优先队列
none: 只是用普通队列,本质上和statements相同,都是只是用一个队列
thread_pool_high_prio_tickets
取值0~4294967295,当开启了优先队列模式后(thread_pool_high_prio_mode=transactions),每个连接最多允许thread_pool_high_prio_tickets次被放到优先队列中,之后放到普通队列中,默认为4294967295
thread_pool_idle_timeout
worker线程最大空闲时间,单位为秒,超过限制后会退出,默认60
thread_pool_max_threads
threadpool中最大线程数目,所有group中worker线程总数超过该限制后不能继续创建更多线程,默认100000
thread_pool_oversubscribe
一个group中线程数过载限制,当一个group中线程数超过次限制后,继续创建worker线程会被延迟,默认3
thread_pool_size
threadpool中group数量,默认为cpu核心数,server启动时自动计算
thread_pool_stall_limit
timer线程检测间隔,单位为毫秒,默认500
性能测试
测试硬件:
mysql服务器:mybxxxxxx.cm3
mytest压力机:myayyyyyy.cm3
两台机器都为24核心cpu,192G内存,bufferpool: 70G
性能指标:
QPS/TPS/RT(Response time)
实验对照
one-thread-per-connection: 基准数据
threadpool(high prio off): 线程池方案,优先队列不开启
threadpool(high prio on): 线程池方案,开启优先队列
只读场景
tc_read_1_3(读取数据占所有数据1/3),tcbuyer_0000(数据量120G),sql序列:
set autocommit=0; select...; commit; select...; commit;... |
QPS:
RT:
结果说明
threadpool方案,开启优先队列后能够在高并发下维持最高性能,且RT更低,而不开启优先队列,在高并发下性能甚至会比one-thread-per-connection低,原因:本测试中,sql执行序列为:
set autocommit=0; select…; commit; select…; commit;…在不开启优先队列的情况下,因为线程池以sql为调度单位,导致活跃事务链表相对于one-thread-per-connection更长
thread_pool_stall_limit影响:
1. thread_pool_stall_limit = 500(default,RT 50ms,活跃事务589个,QPS:22K)
- - --------- -----load-avg---- ---cpu-usage--- ---swap--- -QPS- -TPS- -Hit%- ---innodb rows status--- ------threads------ --------tcprstat(us)-------- |
$mysql -uroot -e "show engine innodb status\G"|grep 'TRANSACTION'|grep 'ACTIVE'|wc -l |
2. thread_pool_stall_limit = 50(RT 30ms,活跃事务233个,QPS:43K)
- - --------- -----load-avg---- ---cpu-usage--- ---swap--- -QPS- -TPS- -Hit%- ---innodb rows status--- ------threads------ --------tcprstat(us)-------- |
$mysql -uroot -e "show engine innodb status\G"|grep 'TRANSACTION'|grep 'ACTIVE'|wc -l |
3. thread_pool_stall_limit = 30(RT 30ms,活跃事务127个,QPS:52K)
- - --------- -----load-avg---- ---cpu-usage--- ---swap--- -QPS- -TPS- -Hit%- ---innodb rows status--- ------threads------ --------tcprstat(us)-------- |
$mysql -uroot -e "show engine innodb status\G"|grep 'TRANSACTION'|grep 'ACTIVE'|wc -l |
解释:thread_pool_stall_limit 是后台timer线程检测任务是否堵塞的时间间隔,在并发压力较大时,该参数设置过大可能会造成timer线程无法及时唤醒/创建worker线程,从测试结果中可以看出该参数设置为最大可接受的RT比较合适(应用期望DB的最大响应时间)
读写场景>/h4>
tc_rw_5_1(读写压力为5:1),tcbuyer_0000(数据量约120G),sql序列:
set autocommit=0; update...;update;commit/select...;select...;commit/update...;select...;commit/... |
QPS + TPS
RT:
结果说明
开启优先队列的threadpool在高并发下可以保持最高性能,同时rt也较小,而one-thread-per-connection与不开启优先队列的threadpool调度方案在高并发下性能急剧下降,rt明显升高
测试结论
开启优先队列的threadpool通过优先调度已开启事务缩短事务执行时间,在高并发下可以保持最高性能,同时保证较小的rt
MySQL 参数配置
[mysqld_safe] |
MySQL 5.6 Threadpool(优先队列)介绍及性能测试【转】的更多相关文章
- 查看MySQL数据库表的命令介绍
如果需要查看MySQL数据库中都有哪些MySQL数据库表,应该如何实现呢?下面就为您介绍查看MySQL数据库表的命令,供您参考. 进入MySQL Command line client下查看当前使用的 ...
- mysql高可用方案MHA介绍
mysql高可用方案MHA介绍 概述 MHA是一位日本MySQL大牛用Perl写的一套MySQL故障切换方案,来保证数据库系统的高可用.在宕机的时间内(通常10-30秒内),完成故障切换,部署MHA, ...
- python模块介绍- multi-mechanize 性能测试工具
python模块介绍- multi-mechanize 性能测试工具 2013-09-13 磁针石 #承接软件自动化实施与培训等gtalk:ouyangchongwu#gmail.comqq 3739 ...
- Mysql Binlog三种格式介绍及分析【转】
一.Mysql Binlog格式介绍 Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的sql都会记录在 ...
- windows下重置mysql的root密码方法介绍(转)
自己在内网操作的,遇到了一些的问题,其中一个是需要重置密码的,所以网上找了两篇文章,都有一些借鉴的地方. 版本mysql5.7.2,linux系统 除了参考文章还有几点说明: service mysq ...
- Amoeba mysql读写分离搭建及介绍
Amoeba mysql读写分离搭建及介绍 推荐: http://blog.chinaunix.net/uid-20639775-id-154600.html
- MySQL 中的默认数据库介绍
MySQL 中的默认数据库介绍:https://dataedo.com/kb/databases/mysql/default-databases-schemas 默认数据库 官方文档 informat ...
- java中ThreadPool的介绍和使用
文章目录 Thread Pool简介 Executors, Executor 和 ExecutorService ThreadPoolExecutor ScheduledThreadPoolExecu ...
- MySQL备份还原——mysqldump工具介绍
mysqldump是一款MySQL逻辑备份的工具,他将数据库里面的对象(表)导出成SQL脚本文件.有点类似于SQL SEVER的"任务-生成脚本"的逻辑备份功能.mysqldump ...
随机推荐
- [asp.net core]project.json(2)
摘要 上篇文章介绍了project.json中的一部分属性.属性真的比较多,所以分开了,考虑到其中的英文比较简单,也不再进行翻译了,从英文原文中,直接粘贴过来了. project.json(1) pr ...
- MEF搜索范围
MEF对扩展组件的查找范围通常有三个: AssemblyCatalog:从某个程序集中查找. ApplicationCatalog:在应用程序所在的目录下查找. DirectoryCatalog:在某 ...
- hdu4782 Beautiful Soup (模拟)
http://acm.hdu.edu.cn/showproblem.php?pid=4782 2013成都区域赛全题PDF:http://acm.hdu.edu.cn/downloads/2013Ch ...
- spring缓存Ehcache(入门2)源码解读
Ehcache缓存: 解读: Ehcache缓存是在继承spring缓存核心类CacheManager的基础上实现的. 常用类: EhCacheCacheManager:继承自CacheManager ...
- JAVA之Socket编程
网上对Socket的诠释很多,也很全,在这里我就不多说了,总之,现在的网络处处都在使用Socket.本帖是一个Socket的例子,用来模拟一个简单的登录系统,只有核心代码,访问数据库.输入神马的统统没 ...
- wordpress如何批量关闭旧日志留言功能
于一些wordpress技术博客或者其他wordpress博客来说,一些旧日志的内容可能已经过时了,但是一些读者,还是对一些问题“纠缠不清”或者“喋喋不休”,怎么办,把留言关了就好了: UPDATE ...
- nginx的那些内置变量
nginx在配置文件nginx.conf中可以使用很多内置变量,配置如下: location /info { add_header 'Content-Type' 'text/html'; echo & ...
- 解决Button设置disabled后无法执行后台代码问题
一.开始调式下面的程序,发现Button在js中设置disabled后无法执行后台代码(btnsave_Click)问题 <asp:Button ID="btnsave" r ...
- smem – Linux 内存监视软件
导读 Linux 系统的内存管理工作中,内存使用情况的监控是十分重要的,在各种 Linux 发行版上你会找到许多这种工具.它们的工作方式多种多样,在这里,我们将会介绍如何安装和使用这样的一个名为 sm ...
- Unity手游之路<七>角色控制器
Unity手游之路<七>角色控制器 我们要控制角色的移动,可以全部细节都由自己来实现.控制角色模型的移动,同时移动摄影机,改变视角.当然Unity也提供了一些组件,可以让我们做更少的工作, ...