数据库连接是有限的、昂贵的资源,一个数据库连接对象对应一个物理数据库的连接,如果每次数据库操作都创建新的连接,使用完后释放,会导致系统性能低下,这就引出了连接池的概念。

连接池的必要性

数据库连接池是负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,可以视作一个存放数据库连接的容器。

数据库连接池采用了资源池设计模式,用于资源共享,避免资源的频繁分配与释放问题。同时便于统一管理,可以通过对连接池的控制,限制系统与数据库的连接,监视数据库的连接数量和使用情况。

1、不使用连接池流程

下面以访问MySQL为例,执行一个SQL命令,如果不使用连接池,需要经过哪些流程。

  1. TCP建立连接的三次握手
  2. MySQL认证的三次握手
  3. 真正的SQL执行
  4. MySQL的关闭
  5. TCP的四次挥手关闭

为了执行一条SQL,却多了非常多网络交互。
优点:实现简单
缺点:

  • 网络IO较多
  • 数据库的负载较高
  • 响应时间较长及QPS较低
  • 应用频繁的创建连接和关闭连接,导致临时对象较多,GC频繁
  • 在关闭连接后,会出现大量TIME_WAIT 的TCP状态(在2个MSL之后关闭)

2、使用连接池流程

使用数据库连接池的步骤:

第一次访问的时候,需要建立连接。 但是之后的访问,均会复用之前创建的连接,直接执行SQL语句。
优点:

  • 较少了网络开销
  • 系统的性能会有一个实质的提升
  • 没了麻烦的TIME_WAIT状态

3、数据库连接数设置

系统可采取设置最小连接数和最大连接数等参数来控制连接池中的连接。最小连接数是系统启动时创建的数据库连接数。最小连接数小,则启动快,响应慢。通常设置较大一些。最小连接数可以设置为5个-10个。最大连接数根据硬件配置设置,4核心机器可以设为10个,8核心可以设为20个。

HikariCP的默认的最大和最小连接数是10。建议是设置最大和最小连接数为相同的值,维护一个高性能连接池。

4、连接池数量设置原理,计算公式

第一点,首先我们要知道单核CPU“同时”运行多个线程,只不过是假象。单核CPU同一时刻只能执行一个线程,然后操作系统切换上下文,CPU 核心快速调度,执行另一个线程的代码。这其中便涉及到了大量上下文切换带来的额外性能损耗。

第二点,由上可知,一个N核心服务器,设置数据库连接数为N便能提供最优性能。然而,实际情况会受到磁盘IO和网络IO的影响,在IO等待时间内,线程阻塞等待,CPU处于空闲状态。因此,在线程处理I/O密集业务操作时,需要设置线程/连接数比CPU大一些,以提高吞吐量。

连接数的计算公式

连接数 = ((核心数 * 2) + 有效磁盘数)

服务器 CPU 是 4核 i7 的,连接池大小应该为 ((4 * 2) + 1) = 9 ~ 10个。具体需要根据实际业务场景做调整。

业务场景

  • 对于并发访问,可以采用小的数据库连接池,然后将剩下的业务线程放在队列中等待。
  • 如果系统中混合了长事务和短事务,正确的做法应该是创建两个连接池,一个服务于长事务,一个服务于"实时"查询,也就是短事务。

Q.E.D.