浅谈数据库连接池
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。
以上是关于浅谈数据库连接池的主要内容,如果未能解决你的问题,请参考以下文章