MySQL的两个池

SQL 诞生之后,会先去获取一个数据库连接对象,一般是从客户端的数据库连接池中获取。

如果此时连接池中有空闲连接,可以直接拿到复用。但如果没有,则要先判断当前连接数是否达到最大连接数,如果已经满了,当前线程就需要等待其它线程释放连接对象。没满则可以创建一个新的数据库连接使用。

创建数据库连接对象过程:

  1. 从配置文件中获取连接的 IP、端口、账号密码等数据。
  2. 根据配置的地址信息,发起网络请求,建立网络连接(TCP 三次握手)。
  3. 使用账号密码鉴权,成功之后就获取到了一个连接对象。

获取到了一个数据库连接对象之后,这个 SQL 就需要交给 MySQL 的一个线程去执行,MySQL 有两种模式:一个连接对应一条线程模式(one-thread-per-connection) 和 线程池模式(pool-of-threads)。

  • one-thread-per-connection:在创建数据库连接对象时,就会为这个连接对象分配一个线程。后续所有的 SQL,全部由这一个线程执行。会话空闲,这个线程进入等待,不会销毁。
  • pool-of-threads:连接建立不分配线程,当有 SQL 请求时才会丢到线程池中,获取空闲的线程执行,执行完之后归还到线程池中。

这两种模式在 MySQL 的配置文件中进行配置 my.cnf(my.ini)

[mysqld]
thread_handling = one-thread-per-connection
[mysqld]
thread_handling = pool-of-threads  # 开启线程池模式
thread_pool_size = 8  # 线程池分组数,一般设为CPU物理核数

可以通过 SELECT @@thread_handling 命令查看模式。

一条连接对应一条线程模式是默认模式,而线程池模式在 MySQL 企业版才有,社区版只有默认模式。

不管是那种模式,每条 SQL 第一步都会做库、表的校验,但不会重新校验账号密码。库表校验就是库表是否存在,当前账号对这个库是否有权限。

数据库连接池

在获取数据库连接对象,需要经历鉴权、TCP 三次握手;释放数据库连接对象需要经历 TCP 四次挥手。这一过程的开销是很大的,所以使用池化技术维护这种资源。
比较知名的数据库连接池是阿里的 Druid,作用就是:复用连接对象,避免频繁创建和销毁连接。

MySQL 线程池

池化技术一个最主要的作用就是复用,避免频繁创建和销毁。那么如果使用一个数据库连接池,意味着在连接池中这些连接对象并不会被销毁,又因为网络连接是长连接,这就意味着 MySQL 分配给连接对象的线程并不会被销毁,也就不会频繁创建和销毁线程了。那么这个线程池模式存在的意义是什么?

看起来很正确,使用数据库连接池就能间接管理到 MySQL 的线程了。但是如果没有使用连接池呢?
就算使用了连接池,但是一个 MySQL 实例可能会有多个服务使用,即多个客户端,每个客户端都只会维护一个自己的数据库连接池,服务躲起来了,自然总的连接对象也就多了,那么 MySQL 就会面临创建很多线程的要求了。

线程数量过多就会带来三个问题:

  1. 线程上下文切换成本增加。
  2. 内存消耗增加。
  3. 锁竞争增加。

所以,MySQL 线程池的作用不但是复用线程,避免频繁创建和销毁线程(这不是主要目的),还有一个作用是限制 SQL 的并发度。这样可以在高并发场景下提升数据库的稳定性,不至于被直接打崩。

连接池维护的是网络连接,线程池池维护的是工作线程

posted @ 2026-09-02 07:38  yairr  阅读(4)  评论(0)    收藏  举报