Hi,运维,你懂Java吗--No.8:数据库连接池

        作为运维,你不一定要会写Java代码,但是一定要懂Java在生产跑起来之后的各种机制。

        本文为《Hi,运维,你懂Java吗》系列文章 第八篇,敬请关注后续系列文章

        欢迎关注 龙叔运维(公众号) 持续分享运维经验

前言
       

        本篇对java的数据库的连接池进行讲解。

        主要站在运维角度讲解主流数据库连接池的配置参数,以及常见报错场景

        

1、为什么使用数据库连接池?

        如果不使用数据库连接池,那么应用每次访问数据库都需要进行连接的创建,频繁的进行TCP握手、挥手。造成大量消耗,降低系统性能和并发能力。

        数据库连接池管理维护一定数量的数据库连接,在应用需要连接数据库的时候进行分配,极大的降低了消耗,并能更好的管理对数据库的连接。

2、什么是数据库连接池?

        下图简单介绍了数据库连接池在应用中起到的作用,以及一些常见的配置指标

3、数据库连接池有哪些?

        目前的数据库连接池有Hikari,druid,dbcp,tomcat-jdbc,c3p0,BoneCP,Proxool,下面分别简单介绍下

        整体来说,更为推荐Hikari 和 druid

        Hikari性能最强

        druid扩展性、监控性最强

3.1、c3p0

        历史悠久,代码及其复杂,不利于维护。并且存在deadlock的潜在风险,不建议使用

3.2、BoneCP

        现在已经不更新了,转到了HiKariCP上。不建议使用。

3.3、Proxool

        评测说在并发较高的情况下会出错,且现在维护力度已经很小,不建议使用。

3.4、dbcp

        tomcat内置的连接池,单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar
        单线程,并发量低,性能不好,适用于小型系统

3.5、tomcat-jdbc

        由于dbcp的性能不太好,apache又新开发了一款数据库连接池-tomcat jdbc pool,有的地方也称之为JDBC Connection Pool。

3.6、Hikari

        SpringBoot默认使用Hikari(springboot2.0之后)
        SpringBoot项目如果我们通过启动器starter使用JPA或者Mybatis,是默认会使用Hikari数据库连接池的,不需要引入依赖,已经在SpringBoot中包含了。
        号称最快的数据库连接池,强于性能。

3.7、druid

        Druid能够提供强大的监控和扩展功能,强项在于监控

4、数据库连接池配置

        关于各个数据库连接池的核心配置项,我这里对目前最为常用的三个数据库连接池(Druid,Hikari,DBCP)

配置分类参数参数描述DruidHikariDBCP
Druid能够提供强大的监控和扩展功能,强项在于监控SpringBoot默认使用Hikari(springboot2.0之后)
SpringBoot项目如果我们通过启动器starter使用JPA或者Mybatis,是默认会使用Hikari数据库连接池的,不需要引入依赖,已经在SpringBoot中包含了。
号称最快的数据库连接池,强于性能。
tomcat内置的连接池,单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar
单线程,并发量低,性能不好,适用于小型系统
参数描述默认值参数描述默认值参数描述默认值
基础重要获取连接超时时间maxWait无限connectionTimeout30000msmaxWait无限
最小连接数minIdle8minimumIdle官方推荐不设置此值,默认同最大连接数相同10minIdle0
最大连接数maxActive8maximumPoolSize池中最大连接数,包括闲置和使用中的连接10maxActive8
初始化连接数initialSize0initialSize0
连接最长生命周期maxLifetime一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired)

如果不等于0且小于30秒则会被重置回30分钟
1800000ms
连接最大空闲时间idleTimeout连接允许在池中闲置的最长时间
如果idleTimeout+1秒>maxLifetime 且 maxLifetime>0,则会被重置为0(代表永远不会退出);如果idleTimeout!=0且小于10秒,则会被重置为10秒
600000ms
最大空闲连接数maxIdle最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制8
最小空闲连接数minIdle最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建0
其他readOnly从池中获取的连接是否默认处于只读模式falsedefaultReadOnly从池中获取的连接是否默认处于只读模式
autoCommit此属性控制从池返回的连接的默认自动提交行为
设置为false后,事务不会自动提交,导致对数据库的插入修改操作无效,但是查询和删除可以。
truedefaultAutoCommit此属性控制从池返回的连接的默认自动提交行为
poolName连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置HikariPool-1
连接有效性检查有效性检查sqlvalidationQuery连接有效性检查执行sql
如果为null,则下面参数不生效
testOnBorrow
testOnReturn
testWhileIdle
nullconnection-test-query数据库连接测试语句nullvalidationQuery连接有效性检查执行sql
如果为null,则下面参数不生效
testOnBorrow
testOnReturn
testWhileIdle
null
testOnBorrow申请连接时执行validationQuery检测连接是否有效TRUEkeepaliveTime每隔 keepaliveTime 检查连接的有效性,如果db连接不可用,则直接关闭0(关闭)testOnBorrow申请连接时执行validationQuery检测连接是否有效true
testOnReturn归还连接时执行validationQuery检测连接是否有效FALSEtestOnReturn归还连接时执行validationQuery检测连接是否有效false
testWhileIdle申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。FALSEtestWhileIdle申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。false
timeBetweenEvictionRunsMillis1) Destroy线程会检测连接的间removeAbandoned隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。2) testWhileIdle的判断依据60000timeBetweenEvictionRunsMillis在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位. 如果设置为非正数,则不运行空闲连接回收器线程-1
minEvictableIdleTimeMillis连接保持空闲而不被驱逐的最小时间300000minEvictableIdleTimeMillis连接保持空闲而不被驱逐的最小时间
异常调试removeAbandoned用来关闭长时间不使用的连接。RemoveAbandanded功能不建议在生产环境中使用,仅用于连接泄露检测诊断FALSEremoveAbandoned用来关闭长时间不使用的连接。RemoveAbandanded功能不建议在生产环境中使用,仅用于连接泄露检测诊断FALSE
removeAbandonedTimeout打开RemoveAbandanded功能,超过这个时间则会关闭连接,单位秒removeAbandonedTimeout打开RemoveAbandanded功能,超过这个时间则会关闭连接,单位秒
logAbandoned关闭abanded连接时输出错误日志logAbandoned关闭abanded连接时输出错误日志

5、常见数据库连接池报错

5.1、获取数据库连接超时

        原因分析:

        1、瞬间并发突增导致连接被占满

        2、出现了慢SQL。或者连接泄漏

5.1.1、Druid

        报错:com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 60000, active 20, maxActive 20, creating 0

        报错解读分析:

                当前连接池活动连接数为20,最大连接数限制为20,所以没有空闲连接能进行分配,新的请求进来,等了60秒(最大等待时间)之后,抛出了异常

        异常处理解决:

                1、调大最大连接数:

                maxActive = 30

                2、打开连接回收机制:

                removeAbandoned = true 【开启超时回收】
                removeAbandonedTimeout = 180 【超过180秒则进行回收】
                logAbandoned = true 【回收的时候打印相关日志】

        如下就是连接超过removeAbandonedTimeout设置的时间,断开连接之后打印的日志,会打印出对应线程的堆栈先,就可以看出是哪个地方有长时间不释放的数据库连接。

5.1.2、Hikari

        报错:Unable to acquire JDBC Connection Connection is not available, request timed out after 30000ms.

        报错解读分析:

                等待分配数据库连接30秒之后超时报错

        异常处理解决:

                1、调大最大连接数:

                maximum-pool-size: 20

当然 最重要的还是优化代码

5.2、获取到无效连接

5.2.1、Druid

        报错:The last packet successfully received from the server was 1,855,774 milliseconds ago. The last packet sent successfully to the server was 1,855,775 milliseconds ago.

        报错解读分析:

                获取到的数据库连接已经无效,并列出了最后一次成功接收和发送数据的时间间隔

        异常处理解决:

                1、设置连接有效性检查,但会对性能造成影响

                        validationQuery=select 1
                        testWhileIdle=true
                        testOnBorrow=true
                        testOnReturn=true

                2、调整数据库超时配置

                        核查应用到数据库整条链路上的超时时间(中间可能经过负载均衡以及数据库中间件mycat等),整个数据库调用链路超时设置,应该从前到后,超时时间越来越大

                        如MYSQL端的wait_timeout

5.2.2、Hikari

        报错:The last packet successfully received from the server was 212,079 milliseconds ago. The last packet sent successfully to the server was 3,004 milliseconds ago.). Possibly consider using a shorter maxLifetime value.|

        报错:Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl@72b70c61 (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value 

        报错解读分析:

                这两条报错都可以看出是当前获取的连接已经不再有效

        异常处理解决:

                1、数据库连接池设置的连接存活时间超过了数据库端的超时时间,那么调小maxLifetime,但是这种情况较为少见,因为一般数据库端都会是8小时,而Hikari默认是30分钟

                2、数据库端有定时任务kill掉一定时间不活动的数据库连接,或者别的配置(网络,负载均衡,服务器tcp_keepalive_time配置等等原因)导致数据库连接被断掉,也是调小maxLifetime

                建议调整成30秒比较合适

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙叔运维

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值