MySQL thread pool【转】

本文来自:http://blog.chinaunix.net/uid-26896862-id-3993773.html

刚刚经历了淘宝的双11,真实感受到了紧张的氛围。尽管DB淡定的度过,但是历程中的波折,可谓惊心动魄。其中MySQL在大量连接(万级)的场景下,表现出性能远远低于预期,并且出现明显的波动,成为一个非常重要的问题。问题虽然解决,但是后续的思考和方法的探索,仍然继续。以下是在MySQL层增加Thread pool方式,解决大量连接问题。

1、《MySQL Thread Pool: Problem Definition》

MySQL企业版在5.5中,引入了Thread pool方案。本文主要是分析现有方式存在的问题,并引入Thread pool方式以及需求。主要解决MySQL传统连接设计中one-to-one方式(一个连接使用一个线程服务)存在两个方面的问题:

1.1 CPU资源限制

在连接数非常多,并发较大时,CPU可用资源会成为MySQL的连接线程的瓶颈,导致MySQL性能降低。有两个原因:一个是并发数较大时,CPU的cache命中率降低,以及并发线程创建消耗内存资源,可能导致swap影响MySQL的性能;另一个原因是并发较大时,会导致通过临界资源时,产生大量的锁竞争。这些问题在系统层都很难解决,只能通过应用层解决。

1.2 Innodb mutex锁

在并发较大时,会引起Innodb的mutex锁争用。当前解决方法是通过innodb_thread_concurrency参数,但是该参数自身也存在锁争用,同样影响了MySQL的性能。在我们的优化历程中,也尝试通过优化该参数,来解决并发情况下,性能降低的问题。但是测试过程中发现,会有大量的连接等待kernel mutex锁,但是持续的压力会导致MySQL的thread running,最终导致MySQL不可用。

Thread pool主要从四个方面考虑:减少SQL并发,使得有足够的资源;使用线程组,独立管理;使用优先级队列,限制并发执行的事务;避免死锁。

在以上阐述的内容中,几乎涵盖了我们遇到的所有现象和问题,而性能影响会如此严重,是我们始料未及的。

2、《MySQL Thread Pool: Scalability solution》

基于上文中问题定义,本文主要讨论Thread pool的可扩展性解决方案。为了解决并发连接数问题,通常考虑会创建一个线程池,但是会引入可扩展性问题:每个连接或线程建立时,会对公用的数据结构加锁,修改连接或线程的状态信息。这样无异于重新引入热点。

为了避免引入新的问题,Thread pool使用线程组,每个线程组管理组内的连接和线程,线程组之间互相不受影响。并且确保每个线程组内最多有一个活跃的线程连接,这样连接和线程建立时,仅对单个线程组内的数据结构加锁,文中称之为分治法。

在文章回复中,有一个问题非常重要:线程组的引入,会出现当等待线程组时,请求不能进入而阻塞连接,而该问题会通过定时器的方式解决。另一个问题是:通过限制每个用户的连接数,而MySQL层通过innodb_thread_concurrency参数控制,来控制并发连接数。对于第二个问题,当应用达到一定重量级时,限制用户连接数变得比较困难。假设有几千台应用服务器,每个应用服务器1~2个数据库连接,同样会出现并发连接过多的问题。也就是说通过用户连接数限制,治标不治本。

3、《MySQL Thread Pool: Limiting number of concurrent statement executions》

上文回复中,提出当线程组引入后,SQL语句可能会导致线程组的等待,阻塞大量查询。本文中针对该问题,提出了通过定时器的方式解决。当SQL查询执行超过定时器的时间,线程组将会设置为不可用。

此外,当查询由于锁被阻塞时,线程会等待超时时间,然后处理新的查询请求,从而保证了线程组的可用。

4、《MySQL Thread Pool: Limiting number of concurrent transactions》

对于事务的并发控制,Thread pool采用优先级队列的方式解决。为了避免大事务导致线程组不可用,引入了thread_pool_prio_kickup_timer参数,当事务超过参数设置的超时时间时,等待线程组的查询会被移到高优先级队列中。为了避免过多的移动,Thread pool限制每个线程组在10ms内最多移动一次。

通过优先级队列,可以很大程度上解决因为事务阻塞,而产生大量查询超时的问题,还解决了其他线程组空闲的情况。

5、《MySQL Thread Pool: When to use?》

Thread pool的原理和实现在以上文章中进行了详细的解释,但是什么时候用呢?本文指出根据threads_running的监控值,来判断是否使用Thread pool。当threads_running值超出了MySQL的处理能力时,Thread pool将会保护MySQL server。

此外,Thread pool和innodb_thread_concurrency参数一起使用,可以更好的控制并发。Thread pool主要在Server层,在事务开始之前进行限制,innodb_thread_concurrency在事务处理中进行控制。

特别指出,如果查询为短查询,Thread pool会非常有效。如果查询为长查询,Thread pool会有性能影响。

6、《MySQL Thread Pool vs. Connection Pool》

针对文章2中回复的第二个问题,本文详细解释了Thread pool和Connection pool两者的区别。Thread pool主要是MySQL端采取的线程控制,用于限制MySQL实际处理的SQL并发。而Connection pool是在应用的客户端来限制,连接到MySQL Server的线程数。

在某些情况下,Connection pool并非所有的连接都有活跃的事务,但是会在MySQL Server中建立大量的连接。而通过Thread pool,可以减少MySQL Server的连接数。

7、《MySQL Thread Pool: Optimal configuration》

本文主要介绍Thread pool使用的参数进行详细的说明,主要包括:thread_pool_size指定线程池大小,默认值为16;thread_pool_stall_limit执行线程池超时时间,默认值为6(60ms);thread_pool_prio_kickup_timer限制优先级队列移动的超时时间,默认值为1000(1s);thread_pool_algorithm指定线程池算法,暂不支持;thread_pool_max_unused_threads查看当前最大未使用的线程数。

在实际使用中,根据数据库服务器的性能,MySQL Server的使用情况,以及应用查询的情况,调整这些参数,从而达到最佳的性能。

8、《MySQL Thread Pool: Benchmarking》

本文通过压力测试,比较使用Thread pool前后,性能的影响。通过测试结果可知,使用Thread pool在连接并发数较大时,性能可以稳定在较高水平,并没有由于连接数的增加,导致MySQL性能的骤减。

官方测试结果如下图所示,


结论

Thread pool的引入,解决了MySQL传统连接设计中one-to-one方式带来的不足。此外,使用线程组的方式,避免引入新的可扩展问题;使用定时器,解决长查询阻塞线程组的问题;通过优先级队列,解决大事务问题。

从测试结果来看,Thread pool在连接并发数较大时,性能可以稳定在较高水平,而没有由于连接数的增加,导致MySQL性能的骤减。

由于MySQL企业版未开放源码,只能通过黑盒测试进行评估。但是实现的原理和处理策略,对于评估开源Thread pool的实现,都非常有益。

参考

1、《MySQL Thread Pool: Problem Definition》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-problem-definition.html

2、《MySQL Thread Pool: Scalability solution》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-scalability-solution.html

3、《MySQL Thread Pool: Limiting number of concurrent statement executions》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-limiting-number-of.html

4、《MySQL Thread Pool: Limiting number of concurrent transactions》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-limiting-number-of_21.html

5、《MySQL Thread Pool: When to use?》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-when-to-use.html

6、《MySQL Thread Pool vs. Connection Pool》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-vs-mysql-connection.html

7、《MySQL Thread Pool: Optimal configuration》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-optimal-configuration.html

8、《MySQL Thread Pool: Benchmarking》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-benchmarking.html

时间: 2024-08-03 18:55:05

MySQL thread pool【转】的相关文章

MySQL线程池(THREAD POOL)的原理

MySQL常用(目前线上使用)的线程调度方式是one-thread-per-connection(每连接一个线程),server为每一个连接创建一个线程来服务,连接断开后,这个线程进入thread_cache或者直接退出(取决于thread_cache设置及系统当前已经cache的线程数目),one-thread-per-connection调度的好处是实现简单,而且能够在系统没有遇到瓶颈之前保证较小的响应时间,比较适合活跃的长连接的应用场景,而在大量短连接或者高并发情况下,one-thread

【MySQL】mysql buffer pool结构分析

转自:http://blog.csdn.net/wyzxg/article/details/7700394 其他参考: <高性能MySQL> - 8.4.5 InnoDB缓冲池 <MySQL技术内幕InnoDB存储引擎>(第二版内容有所更新) - 2.3 InnoDB体系结构 ############################################## 书中是先对后台线程进行说明,然后对内存部分进行说明,这样更好理解innoDB引擎内存池在使用时的过程. [后台线程

Improve Scalability With New Thread Pool APIs

Pooled Threads Improve Scalability With New Thread Pool APIs Robert Saccone Portions of this article are based on a prerelease version of Windows Server 2008. Details contained herein are subject to change. Code download available at: VistaThreadPool

Whether Thread Pool is Needed for You?

你到底需不需要内存池? 先问自己两个问题: 是否有很多请求需要重复性的进行处理? 而且每个请求是相互独立的? 你是否需要等待IO操作,或是文件操作? 如果你回答YES,那么你需要一个线程池来帮助你. 我们为什么需要内存池? 通常情况下,IO操作都会需要很长的一段时间才能完成.所以,在一个单线程的应用程序中,在IO操作期间,系统资源都会进行等待.如果使用多线程,效率就会大大的提高.所以我们需要线程池更高效的完成多线程操作. 内存池会有什么样的作用? 一个应用程序其实应该避免频繁的创建和销毁线程.

C#多线程实现方法——线程池(Thread Pool)

ThreadPool使用 同步机制 ThreadPool使用 需要定义waitcallback委托形式如 [csharp] view plain copy print? public delegate void WaitCallback(object state); public delegate void WaitCallback(object state); 例如如下例子: [csharp] view plain copy print? static private void ThreadW

MySQL buffer pool中的三种链

三种page.三种list.LRU控制调优 一.innodb buffer pool中的三种页 1.free page:从未用过的页 2.clean page:干净的页,数据页的数据和磁盘一致 3.dirty page:脏页 SQL执行需求: 1.找free页 2.刷新脏页 1.这个页不是热的数据页(刷冷页) 2.这个页最早修改时间(刷修改时间比较早的页,有可能是热页),方便日志文件的覆盖 3.覆盖冷的clean页 为了实现上述需求,innodb用到链表技术(每种链表一种作用,链的存在意义是为了

关于MySQL buffer pool的预读机制

预读机制 两种预读算法 1.线性预读 2.随机预读 对预读的监控 一.预读机制 InnoDB在I/O的优化上有个比较重要的特性为预读,预读请求是一个i/o请求,它会异步地在缓冲池中预先回迁多个页面,预计很快就会需要这些页面,这些请求在一个范围内引入所有页面.InnoDB以64个page为一个extent,那么InnoDB的预读是以page为单位还是以extent? 数据库请求数据的时候,会将读请求交给文件系统,放入请求队列中:相关进程从请求队列中将读请求取出,根据需求到相关数据区(内存.磁盘)读

python mysql Connect Pool mysql连接池 (201

 easy_install mysql-connector-python >>>import mysql.connector as conner >>> conn = conner.connect(user="root", passwd="kaimen", db="zentao", port=3306, pool_name = "mypool", pool_size = 3,) >&g

Thread Pool Model

//////////////////////////////THREA_POOL_MODEL/////////////////////////////////////////////////////// Task { Task(arg){_arg=arg;}   process();  private: _arg; } Thread::Thread(threadPool) {  _touchThreadPool = threadPool } Thread::threadFun(arg:(this