浅谈数据库连接池

Posted 数据库思维

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈数据库连接池相关的知识,希望对你有一定的参考价值。

DB的连接模式及优缺点

应用程序对DB的连接,分为两种模式:

短连接直连:

    应用程序在操作DB的时候,新建DB连接,SQL操作完毕后,关闭连接。

连接池:

    应用程序在启动时,由连接池组件预先按照配置的规则,缓存一定量的DB连接,程序在操作DB的时候,从连接池获取一个连接,SQL操作完毕后,将连接放回到连接池。

各自优缺点:

连接模式
优点
不足
短连接直连
对DB异常感知能力强

1.影响应用并发能力

2.DB连接易被滥用, 导致连接满

连接池

1.缓存DB连接,提升应用并发性能

2.资源重用,降低系统负载

DB异常的及时发现, 依赖于各连接池的具体实现


DB连接池具备的基本功能

1. 连接池初始化

按照预先配置的参数,包括但不限于:

    最大连接数

    最大空闲连接数

    最小连接数

    连接最大空闲时长

初始化连接池组件。


2. DB连接探测

为预防DB Server异常,导致连接池空闲连接的失效,连接池需定期探测空闲连接的可用性。


3. 连接分配

应用程序操作DB时,为其分配一个连接,需具备线程安全性。


4. 连接回收

应用程序操作完DB后,将为其分配的连接,放回到连接池。


5. 连接池关闭

应用程序结束后,关闭DB连接池,释放DB连接。


golang连接池的具体实现

我们按照连接池的基本功能来进行解析, DB以mysql为例,

连接池初始化

常见的做法是, 导入包 "database/sql"、 _"github.com/go-sql-driver/mysql",

然后执行:

sql.Open("mysql", 

"db_user:db_pass@tcp(db_host:db_port)/dbname?timeout=30s")


在Open阶段,  程序会 初始化1个*sql.DB对象,  并不会实际连接DB。同时,开启2个goroutine, 来控制连接的分配和重置。


*sql.DB对象中,与连接池相关的重要配置:

SetMaxOpenConns:  设置最大打开连接数

SetMaxIdleConns:    设置最大空闲连接数

SetConnMaxLifetime:  设置连接可重用的最大时长 (设置后, 会通过1个goroutine间隔Lifetime时间释放过期连接)


DB连接探测

因连接池初始化时,并不会实际连接DB,只有等到实际执行SQL语句时,才会与DB建立连接,故golang连接池未实现旁路进行DB连接探测。


连接分配

当执行db.Query(sql)时,连接池工作,会开始陆续与DB进行连接,将DB连接按照指定的策略,进行连接管理。简略流程如下:


首先,从连接池的空闲连接中获取1个连接给conn, 如果空闲连接不足,且未超过最大连接池时,则新分配1个连接给客户端,如果超过最大连接池,则客户端连接将进入“等待队列”,获取到连接的请求,会继续完成后续SQL操作,直至完成后,进行连接回收。


“等待队列”,是golang中的chan队列, 遵循先进先出原则,默认队列最大值为1000000。


连接回收

连接回收,来自分为2个操作:

1. 正常连接请求完成后,回收已有连接,参考上图。值得注意的是,回收的连接,会优先给等待队列使用 (如果等待队列不为空),否则放回空闲连接池。

2. SetConnMaxLifetime函数中,会有个goroutine程序,扫描过期的连接,从空闲连接池中,进行移除。


连接池关闭

关闭连接池,通过调用*sql.DB的Close()即可,内部逻辑:

1. 阻止新连接进入

2. 循环关闭 空闲连接池

3. 发送stop信号,关联的goroutine任务关闭


正常还在执行SQL的连接,会等待其自动执行完成,不会暴力kill。


以上是关于浅谈数据库连接池的主要内容,如果未能解决你的问题,请参考以下文章

高并发服务优化篇:浅谈数据库连接池

知了堂学习心得浅谈c3p0连接池和dbutils工具类的使用

浅谈Java线程池

浅谈sharding jdbc

数据库连接池是啥

数据库连接池的Java连接池