数据库连接池

什么是数据库连接池

数据库连接池(connection pool)是程序启动时建立多个数据库连接,并将这些连接组成一个连接池,统一进行管理,由程序动态地对池中的链接进行申请,使用,释放。

为什么使用连接池

  1. 资源复用

数据库连接得到复用,避免了频繁的创建、释放连接带来的性能开销,减少内存碎片。

  1. 更快的系统相应速度

数据库连接池初始化时,已经创建多个数据库连接置于池中备用。此时连接的初始化工作已经完成。对于业务请求而言,直接利用连接池中的可用连接,避免了数据库连接的创建和释放,从而缩减了系统整体响应时间。

  1. 统一的连接管理,避免数据库连接泄露

数据库连接由连接池统一管理,最后由连接池统一对连接进行析构,防止有连接没有析构,导致资源泄露

  1. 避免多个线程同时使用一个连接

数据库连接并不是线程安全的,连接池可以防止多个线程同时使用一个连接。

那可不可以一个线程绑定一个线程呢?

这样肯定是可以的,但是如果这样的话,代码的耦合性太高。使用连接池的方式,耦合性低,可修改性更好。

数据库连接的生命周期

  1. TCP三次握手

  2. Mysql认证三次握手

  3. SQL执行

  4. Mysql的关闭

  5. TCP四次挥手

所以数据库连接一般使用的是长连接,如果每次执行SQL都要新建连接的话,连接和释放的代价太大。

数据库连接池使用的也是长连接。

数据库连接池_第1张图片

数据库连接池运行机制

从连接池获取或创建可用连接;

使用完毕后,把连接返回给连接池;

在系统关闭前,断开所有连接并释放连接占用的系统资源;

数据库连接池_第2张图片

连接池和线程池的关系

连接池和线程池的区别

  • 线程池:主动调用任务,当任务队列不为空的时候从队列取任务执行。
  • 连接池:被动被任务使用。当某个任务需要操作数据库时,从连接池中取出一个连接对象,当任务使用完该连接对象后,将该连接对象返还给连接池。

连接池可以和线程池一起使用,一般连接池连接数量和线程池线程数量一致。

连接池设计

连接池CDBPool设计

构造函数

数据库连接池_第3张图片

初始化

img

获取连接

数据库连接池_第4张图片

归还连接

数据库连接池_第5张图片

线程池析构

数据库连接池_第6张图片

析构连接池的时候,需要注意析构的顺序:

  1. 先销毁线程池,确保所有任务都已经执行完退出,已经归还了数据库连接;
  2. 再去销毁连接池

数据库重连机制

Mysql和redis

Mysql重连机制

设置启用自动重连

my_bool reconnect = true;

mysql_options(m_mysql, MYSQL_OPT_RECONNECT, &reconnect); // 配合mysql_ping实现自动重连

检测连接是否正常

int STDCALL mysql_ping(MYSQL *mysql);

描述:

检查与服务端的连接是否正常。连接断开时,如果自动重新连接功能未被禁用,则尝试重新连接服务

器。该函数可被客户端用来检测闲置许久以后,与服务端的连接是否关闭,如有需要,则重新连接。

返回值:

连接正常,返回0;如有错误发生,则返回非0值。返回非0值并不意味着服务器本身关闭掉,也有可能

是网络原因导致网络不通。

Redis重连机制

  1. 使用之前检测连接是否可用

  2. 使用过程中出现连接异常则释放异常

  3. 下一次使用该连接的时候如果发现连接不可用则重新初始化

连接池连接数量设置

连接数设置成多少比较合适?

一般经验公式,如果CPU核数是N

  1. 对于计算密集型,连接数和线程数设置成N + 1;
  2. 对于io密集型,设置成 2 * N + 2。
  3. 对于计算+io密集型,可以算一下计算时间占总的任务时间的比例,最后算出单个CPU的饱和线程数量,同个这个来设置线程数和连接数。

执行同一个任务:

  1. 计算时间,不调用设计io的函数
  2. 计算时间+io时间 = 总的任务时间。

单个CPU的饱和线程数 = 1 / (计算时间 / 总的任务时间)

最终线程数 = 单个CPU的饱和线程数 * CPU核数

上面的这些,仅仅是经验公式,最终还是要根据具体业务结合在一起,经过大量测试,设置适合的参数。

你可能感兴趣的:(Linux,server,数据库,mysql,database,redis,服务器)