一、引子

合理配置一个应用的数据库参数,使其运行良好,这很重要。本文以某务中台的生产环境为例,从Apollo上拔下来一套配置,分析是否合理。

二、MybatisPlus配置

由于我们使用Apollo配置参数,所以分两部分:1.个体配置 2.全局配置

2.1 mybatisplus个体配置

mybatis-plus.mapper-locations = classpath*:/mapper/*Mapper.xml  mapper文件地址匹配
mybatis-plus.type-aliases-package =xx.po 映射的实体包路径,
mybatis-plus.tenant-config.ignoretable = table1,table2
mybatis-plus.auth-config = []
mybatis-plus.global-config.sql-parser-cache = true 缓存sql解析

2.2 mybatis-plus全局配置

mybatis-plus.mapper-locations = classpath:/mapper/*Mapper.xml  mapper文件地址匹配
mybatis-plus.configuration.map-underscore-to-camel-case = true    下划线转驼峰
mybatis-plus.global-config.logic-delete-value = true  逻辑已删除值
mybatis-plus.global-config.logic-not-delete-value = false  逻辑未删除值
mybatis-plus.max-query-records-size = 10000

三、Datasource配置

3.1 dataSource个体配置

=========数据库配置=========
spring.datasource.connectionProperties = druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 通过connectProperties属性来打开mergeSql功能;慢SQL记录5秒

spring.datasource.type = com.alibaba.druid.pool.DruidDataSource 使用德鲁伊连接池
spring.datasource.driver-class-name = org.postgresql.Driver 驱动类名
spring.datasource.url = xx  数据库连接url
spring.datasource.username = ${dbUserName} 用户名
spring.datasource.password = ${dbPassword} 密码
spring.datasource.minIdle = 5 最小空闲连接数 5
spring.datasource.initialSize = 5 初始连接数 5
spring.datasource.maxActive = 100 最大连接数
spring.datasource.maxWait = 60000 获取连接等待超时的时间 60s=1分钟

spring.datasource.filters = stat,wall 监控统计拦截,用于监控界面sql统计
spring.datasource.poolPreparedStatements = false 是否启用缓存PreparedStatements  
spring.datasource.maxPoolPreparedStatementPerConnectionSize = 20 指定每个连接上preStatement缓存数---》未生效!!!

=========健康检查=========
spring.datasource.validationQuery = SELECT 1 连接池的健康检查SQL
spring.datasource.testOnBorrow = false 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
spring.datasource.testOnReturn = false 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
spring.datasource.testWhileIdle = true 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。

#每timeBetweenEvictionRunsMillis毫秒检查一次连接池中空闲的连接,把空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开,直到连接池中的连接数到minIdle为止
spring.datasource.minEvictableIdleTimeMillis = 300000 最小可驱逐空闲时间,连接保持空闲而不被驱逐的最长时间,单位是毫秒 300s=5分钟
spring.datasource.timeBetweenEvictionRunsMillis = 60000 间隔多久才进行一次驱逐检测,单位是毫秒 60s=1分钟

=========连接超时=========
# 关闭abanded连接时输出错误日志,预生产/生产不建议开启,对性能影响
spring.datasource.logAbandoned = false
# 是否清除已经超过“removeAbandonedTimout”设置的无效连接。
spring.datasource.removeAbandoned = true 
# 连接超过指定时间未关闭,就会被强行回收 180s=3分钟
spring.datasource.removeAbandonedTimeoutMillis = 180000

四、源码剖析

看完配置,大家心里还是懵逼对吧,参数如何生效,druid到底如何运行?

下面,带着问题,深入源码,直接剖析druid如何申请连接、释放连接、连接泄露检查。

4.1.申请连接

最终跟进到DruidDataSource的getConnectionDirect(long maxWaitMillis),获取得到连接后,validationQuery有效性检查,源码如下:

1.testOnBorrow =true,先直接校验,执行validationQuery,失败就关闭连接JdbcUtils.close(realConnection);

2.testWhileIdle=true,如果testOnBorrow =false, 测试空闲的连接,执行validationQuery,失败就关闭连接JdbcUtils.close(realConnection);

3.removeAbandoned=true,如果开启了泄露回收:把连接添加进Map<DruidPooledConnection, Object> activeConnections 。供泄露回收时使用。

分支1和2只会有一个执行。

4.2.释放连接

德鲁伊连接池在获取连接时,会调用一次DruidDataSource的init()。方法中createAndStartDestroyThread()开启了一个销毁线程。

销毁连接的线程包含了run(),如下:

在一个for空条件循环中,根据配置的timeBetweenEvictionRunsMillis连接检测间隔时间,执行一次DestroyTask.run()就休眠一次间隔时间。未设置默认60s。(实际源码中定义了60spublic static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = 60 * 1000L;,所以用户未设置,默认60s,上图中else分支sleep1秒不会执行到)

追踪DestroyTask.run()如下:

2个步骤:

  1. shrink()收缩校验
  2. removeAbandoned()连接泄露移除

shrink()收缩校验

DruidDataSource内部定义了DruidConnectionHolder[] 类型的3个数组:

  • 1.connections:可用连接数组。申请连接就从这里数组队尾拿连接。
  • 2.evictConnections:待移除连接数组。
  • 3.keepAliveConnections:待保活检测数组。

塞进数组

shrink()中计算出需要校验的数量checkCount,执行收缩校验核心逻辑:

  • 校验物理连接的超时时间phyTimoutMills:超时放入evictConnections中,等待移除。
  • 空余时间大于minEvictableIdleTimeMillis(受保最小空闲时间),并且索引(poolingCount)小于checkCount的连接则放入evictConnections;
  • 空余时间大于minEvictableIdleTimeMillis(受保最小空闲时间),并且索引大于checkCount的连接,假若空余时间大于maxEvictableIdleTimeMillis则放入evictConnections,否则放入keepAliveConnections中进行keepAlive检测。

如下图:

数组处理

1.evictConnections:待移除连接数组。使用JdbcUtils.close()  关闭连接。

2.keepAliveConnections:待保活检测数组。根据配置的validationQuery查询SQL执行连接可用性校验。校验通过后再put(holder)塞进connections可用连接数组。

4.3.泄露连接移除

如果开启了removeAbandoned ,执行removeAbandoned()。移除泄露连接逻辑如下:

实际上,就是对可能的连接泄露(打开连接后长时间不关闭)兜底。

1)遍历活跃连接Map<DruidPooledConnection, Object> activeConnections。

2)跳过运行中的连接,running定义:执行SQL前赋值true ,执行完后置false。---》问题1得到答案,不会暴力关闭执行中的连接。

3)如果当前连接已连接时间>=removeAbandonedTimeoutMillis ,直接从activeConnections map 中移除。

这里消耗性能主要两步骤:

  • 1.内存中记录+移除泄露连接
  • 2.打印相关日志的IO---》logAbandoned=false 可关闭写日志

spring 的druid 连接池一般不会造成泄露。如果出现连接泄露,应该找到问题解决。---》问题2得到答案,目前关闭了写日志,就剩下了第一点“内存占用+过滤的性能”成本,要求不高的场景可以作为兜底方案使用。如果项目已稳定,推荐关闭。

五.分析&总结

本节为我们根据:申请、释放连接相关的参数配置,剖析策略是否合理。

5.1 配置分析

spring.datasource.testOnBorrow = false 申请连接时执行validationQuery检测连接是否有效

spring.datasource.testOnReturn = false 归还连接时执行validationQuery检测连接是否有效

spring.datasource.testWhileIdle = true testOnBorrow=false时才生效,申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。

spring.datasource.initialSize = 5 初始连接数 5

spring.datasource.maxActive = 100 最大连接数

spring.datasource.minIdle = 5 最小空闲连接数 5

timeBetweenEvictionRunsMillis= 60000 60s=1分钟检测一次

minEvictableIdleTimeMillis=300000 300s=5分钟 最小空闲不移除时间

maxEvictableIdleTimeMillis 未设置最大空闲移除时间,默认DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 60L * 7 = 7小时。

keepAlive: 未设置保活开关,默认false关闭。不执行保活测试策略。

上述配置对应的策略:

1.初始策略

初始5个连接,最多可开启100个连接。

2.申请策略

申请连接的时候检测,如果连接空闲时间大于1分钟(检测间隔时间),执行validationQuery检测连接是否有效。---》这里可确保我们空闲时间超过1分钟的连接,校验后使用。

3.回收策略

每一分钟执行一次检测,策略如下:

1.连接空闲小于5分钟,不移除。

2.连接空闲大于5分钟,保留”minIdle设置的5个idle连接”,可移除(总数-5)个连接。

3.连接空闲大于7小时,可移除“minIdle设置的5个idle连接”。---》因为没有设置maxEvictableIdleTimeMillis ,默认空闲7小时后才会移除。不过一共就5个倒也没什么事。

4.连接空闲5分钟~7小时,由于没开启keepAlive保活开关,无法对“minIdle设置的5个idle连接”保活测试。-->minIdle设置的5个idle连接,这段时间一直不回收,也不做保活测试,连接是否有效无法保证。

5.2总结

1.现有项

removeAbandoned=true 开启连接泄露检测,要求不高的场景可以作为兜底方案使用。如果项目已稳定,推荐关闭。

2.可添加项

phyTimeoutMillis:看需要开启。物理超时时间。不管空闲时间,超时直接移除。---》这个是终极兜底方案,可以确保超时强制移除。

maxEvictableIdleTimeMillis:建议开启,实现精细化控制。

keepAlive: 建议开启。可针对“minIdle设置的空闲连接”,进行保活测试,从而提升连接的质量。

postgreSql最佳配置详解(connection 申请、回收策略)的更多相关文章

  1. druid 参数配置详解

    druid 参数配置详解 */--> druid 参数配置详解 Table of Contents 1. 初始化连接 2. 参数配置及说明 3. 注意事项 3.1. 底层连接 3.2. 空闲检查 ...

  2. 阿里云slb和ucloud负载均衡ulb添加ssl证书将http服务https化的配置详解

    阿里云和ucloud服务器配置ssl证书将http服务https化的配置详解 项目背景: 苹果App于2017年1月1日将启用App Transport Security安全功能,即强制App通过HT ...

  3. Tomcat记录-tomcat常用配置详解和优化方法(转载)

    常用配置详解 1 目录结构 /bin:脚本文件目录. /common/lib:存放所有web项目都可以访问的公共jar包(使用Common类加载器加载). /conf:存放配置文件,最重要的是serv ...

  4. tomcat常用配置详解和优化方法

    tomcat常用配置详解和优化方法 参考: http://blog.csdn.net/zj52hm/article/details/51980194 http://blog.csdn.net/wuli ...

  5. [转]阿里巴巴数据库连接池 druid配置详解

    一.背景 java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池.数据库连接池有很多选择,c3p.dhcp.proxool等,druid作为一名后起之秀,凭借其出色 ...

  6. redis配置详解

    ##redis配置详解 # Redis configuration file example. # # Note that in order to read the configuration fil ...

  7. JSHint配置详解

    Also available on Github JSHint配置详解 增强参数(Enforcing Options) 本类参数设为true,JSHint会产生更多告警. bitwise 禁用位运算符 ...

  8. 日志分析工具ELK配置详解

    日志分析工具ELK配置详解 一.ELK介绍 1.1 elasticsearch 1.1.1 elasticsearch介绍 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分 ...

  9. springdata+redis配置详解

    springdata设计初衷是位简化数据类型和数据的持久化存储,它并不局限是关系型数据库还是nosql数据库,都提供了简化的数据库连接,让数据获取变得更加的简单.所有这些的实现有统一的api提供. 本 ...

  10. CentOS6.5下VNC Server远程桌面配置详解

    参考文献: (总结)CentOS Linux下VNC Server远程桌面配置详解 远程桌面连接工具VNC——license Key 我的下载地址为 太平洋下载 VNC连接黑屏的问题 centos 6 ...

随机推荐

  1. 小样本学习在文心ERNIE3.0多分类任务应用--提示学习

    小样本学习在文心ERNIE3.0多分类任务应用(提示学习) 项目链接: https://aistudio.baidu.com/aistudio/projectdetail/4438610?contri ...

  2. 从github上下载代码到本地

    相关链接: 码云(gitee)配置SSH密钥 码云gitee创建仓库并用git上传文件 git 上传错误This oplation equires one of the flowi vrsionsot ...

  3. 从嘉手札<2024-1-10>

    冬月初零 年岁缭绕 秋月无影 倏尔迢迢 暗章难牧 纵使再怎么保有年少飞扬的内心 时光仍带去了我二十六年的光阴 出乎意料的收到了很多人的祝福 可喜的是 仍有不少人记挂着我 于我而言 无疑是莫大的荣幸和欣 ...

  4. 希捷推出IronWolf Pro 24TB硬盘:CMR构建、285MB/s传输速率

    希捷推出了全新IronWolf Pro 24TB硬盘,采用3.5寸规格,满足中小企业和NAS环境需求. 据了解,新款硬盘采用了希捷AgileArray技术,针对NAS系统进行了优化.其通过双平面平衡和 ...

  5. java将集合里面的元素拼接为一条String字符串

    java将集合里面的元素拼接为一条String字符串 1️⃣ 随便创建一个list集合,往里面塞入元素 2️⃣ 第一种方式:通过foreach循环实现 但是通过这种方式只能将list集合里面的元素取出 ...

  6. Nebula Siwi:基于图数据库的智能问答助手思路分析

      本文重点分析 Nebula Siwi 智能问答思路,具体代码可参考[2],使用的数据集为 Basketballplayer[3].部分数据和 schema 如下所示: 一.智能问答可实现的功能 1 ...

  7. 小知识:TFA收集日志报错空间不足

    今天在某客户环境下分析某节点驱逐的故障,发现有安装TFA,所以使用一键收集包含故障时刻的日志 tfactl diagcollect -from "2020-08-14 03:00:00&qu ...

  8. Linux--split命令(将一个大文件拆分成多个小文件)

    一.split命令简介 split是Linux系统中的一个文件拆分命令,它可以将一个大文件拆分成多个小文件.这对于处理大型文件,或者需要将数据分解到多个文件中的场景非常有用. 二.split命令的使用 ...

  9. [SpringBoot][Maven]关于maven pom文件的packaging属性

    关于maven pom文件的packaging属性 前几天在调试源码运行程序的时候,因为将项目中pom文件的packaging属性用错导致源码包无法引入使用而报Bean注入错误,在此进行总结整理记录. ...

  10. [Redis] Redis的三大缓存异常原因分析和解决方案

    Redis的三大缓存异常原因分析和解决方案 缓存的三个异常分别是缓存击穿.缓存雪崩.缓存穿透.这三个问题一旦发生,会导致大量的请求积压到数据库层,并发量巨大的情况下很有可能导致数据库宕机或是故障,造成 ...