简介: 针对数据库连接池到DRDS连接探活的优化

1. 问题背景

近期在给某专有云客户进⾏云产品应⽤性能优化分析时,发现了⼀个有趣的关于DRDS使⽤层⾯的问题,这⾥给⼤家分享⼀下。
使⽤过DRDS产品的同学都知道在DRDS中,未分库分表的数据表会存储在“0号库”上,对于这些表操作的SQL会被分发到“0号库”上执⾏。所以⼀般情况下,0号库所在实例的压⼒会⽐其它实例的压⼒稍⼤⼀些。近期分析该客户的数据库性能时,发现客户使⽤的DRDS下0号库所在的RDS实例的压⼒明显⽐其它RDS实例⾼出许多。


图1:SQL语句平均每秒执行次数及事务数

2. 原因分析

通过查看0号库所在的RDS实例的执⾏SQL发现,有⼤量的 SELECT 'x' 的查询语句。检查应⽤侧代码后发现,这个查询语句是应⽤侧连接池配置的连接探活SQL,所有的连接池实现⼏乎都有这个功能,可以通过探活SQL检测连接当前是否可⽤。
那么问题来了:

  1. 为什么只有0号库所在RDS上会有⼤量此类的语句?
    DRDS中不带表名的(⽐如 SELECT 'x')SQL和show命令都会被下发到0号库执⾏。

  2. 对于客户端来说这种连接检测是否有⽤?

答案⼀定是有⽤的,因为如果因⽹络闪断或其它原因导致的连接状态不可⽤,即使获取到了连接对象,也不能进⾏数据访问操作。所以这个检测是有必要的,但对于使⽤DRDS作为数据源的场景来说,⽬前配置的检测⽅式是存在问题的。
对于传统的数据库使⽤⽅式,客户端是直接连接到底层数据库的,如下图。探活SQL是直接发到连接的数据库执⾏,这种场景下使⽤ SELECT 'x' 检测客户端到数据库的连接是没有问题的。


图2:客户端连接到数据库

⽽对于使⽤DRDS作为数据源的场景来说,探活语句在发送到DRDS服务后,会被转发到0号库执⾏,这就意味着这个探活SQL实际上检测的是客户端-->DRDS-->0号库的链路是否正常。


图3:客户端通过DRDS连接到数据库

这⼀点可以从DRDS上看 SELECT 'x' 的执⾏计划得到证实,如下:


图4:执⾏结果1

实际上,这样的数据源连接检测是没有意义的。因为:

  • 第⼀,数据源后端实际上只检测了DRDS到0号库的连接状态,DRDS到其它分库的连接状态并未检测。但真正执⾏SQL时,DRDS是有可能将解析后的SQL下发到其它分库上执⾏的。

  • 第⼆,客户端探活SQL的作⽤主要是为了保证客户端连接池与数据源之间的连接是可⽤的。对于数据源背后的情况应该由数据源本身维护,即由DRDS本身到RDS的连接池保障连接可⽤性,⽽不应该通过客户端的探活功能来保证。

3. 解决方法

明⽩以上内容后,我们解决问题的⽅案就⽐较清楚了,实际上我们只需要让客户端连接池检测客户端到DRDS的连接状态即可。那有没有这样的检测⽅法呢?
答案当然是有的,经过与DRDS研发同学确认,将探活SQL修改为 SELECT 'x' FROM dual 即可。
修改后,再次在DRDS查看执⾏计划,如下:


图5:执⾏结果2

在应⽤侧修改连接池的探活SQL配置后,从0号库所在实例上看,已经看不到探活SQL的执⾏记录,⽽且从修改前和修改后0号库所在实例的压⼒来看,效果也⽐较明显,0号库的压⼒相⽐之前下降了⼤概80%左右。


图6:SQL语句平均每秒执行次数及事务数2

4. 连接池参数配置

⾄此,0号库压⼒过⾼的问题解决了,下⾯我们聊聊为什么会有⼤量的探活语句出现。
探活机制实际上是数据源连接池通⽤的⼀种检测机制,可以检测连接池内的连接对象是否真的可⽤。拿Druid连接池举例,探活SQL是通过数据源的 validationQuery 属性配置的。与之相关的配置属性还有:testOnBorrow、testWhileIdle、testOnReturn、timeBetweenEvictionRunsMillis、 minEvictableIdleTimeMillis。官⽅解释如下:

  • testOnBorrow:申请连接时执⾏ validationQuery 配置的探活语句检测连接是否有效。

  • testWhileIdle:申请连接的时候检测,如果空闲时间⼤于timeBetweenEvictionRunsMillis ,执⾏ validationQuery 检测连接是否有效。

  • testOnReturn:归还连接时执⾏ validationQuery 检测连接是否有效。

  • timeBetweenEvictionRunsMillis:有两个含义

    1)Destroy线程检测连接的间隔时间,如果连接空闲时间⼤于等于 minEvictableIdleTimeMillis 则关闭物理连接。
    2)testWhileIdle 的判断依据,详细看 testWhileIdle 属性的说明。

  • minEvictableIdleTimeMillis:连接保持空闲⽽不被驱逐的最⼩时间。

⽂章前⾯描述的出现⼤量探活SQL的情况是因为应⽤将连接池的testOnBorrow设置成了true,所以在每次应⽤获取连接时,都会执⾏ validationQuery 配置的探活语句检测连接是否有效。虽然通过前⾯的优化步骤,已经降低了0号库的压⼒,使探活语句不下发到0号库执⾏。但探活语句仍会在DRDS实例上执⾏,DRDS实例的压⼒并未减轻。通过上⾯对Druid数据源属性配置的说明可以了解到,如果将 testOnBorrow 或 testOnReturn 打开,会对系统性能有⼀定的影响,因为每次都会在获取连接时多执⾏⼀次查询来检测连接是否可⽤。因此推荐使⽤如下的配置:

  • testWhileIdle=true【如果获得的连接为“空闲连接”,则会进⾏探活检测,如果检测失败,会将此连接从连接池移除,尝试重新从连接池获取连接】

  • timeBetweenEvictionRunsMillis=60000【Destroy线程每隔1分钟对连接池内部的空闲时间>= minEvictableIdleTimeMillis的连接进⾏探活检测,如果检测失败,会将连接从连接池移除】

  • minEvictableIdleTimeMillis=60000【如果连接闲置1分钟,则认为此连接为“空闲连接“】

这样设置完成后,只有在获取到“空闲连接”时,才会进⾏探活检测,⼤⼤降低了业务⾼峰时段的探活频率。同时,也可通过适当缩短minEvictableIdleTimeMillis 的值,兼顾由于⽹络闪断或其它原因导致的连接不可⽤的情况,减少业务出错的概率,在系统性能和可⽤性之间找到⼀个平衡点。

作者:刘维

原文链接

本文为阿里云原创内容,未经允许不得转载

针对数据库连接池到DRDS连接探活的优化相关推荐

  1. 数据库连接池之自定义连接池(mysql)

    数据库连接池之自定义连接池(mysql) 上一篇博文是"基于mysql的JDBC的增删改查的封装":点击可查看 今天本仙在昨天JDBC封装增删改查的基础上实现自定义的数据库连接池: ...

  2. 01_数据库连接池,数据源,ResultSetMetaData,jdbc优化

     一.数据库连接池 1. 什么是连接池 传统的开发模式下,Servlet处理用户的请求,找Dao查询数据,dao会创建与数据库之间的连接,完成数据查询后会关闭数据库的链接. 这样的方式会导致用户每 ...

  3. 数据库连接池 ( 四 ) Druid 连接池

    3.2.Druid 连接池 Druid:Druid不仅是一个数据库连接池,还包含一个ProxyDriver.一系列内置的JDBC组件库.一个SQL Parser. 支持所有JDBC兼容的数据库,包括O ...

  4. 数据库连接池和Tomcat连接池的配置问题

    在做系统优化的时候师哥给我们提了一个连接池的概念,问我们有没有配置,我对这个概念一无所知,于是进行了一些研究,连接池有很多,比如WCF.EF还有数据库.CAS也可以配连接池,这些连接池用通俗的语言来说 ...

  5. php oracle数据库连接池,数据库管理Oracle 连接池信息的修改

    最近项目中用到的Oracle数据库在服务器上是建了多个表空间供不同系统使用,两个系统同时在使用过程中,正在开发的一个项目在测试运行时,时不时就出现连接池满了,连接不上的问题,为此查了下怎么修改Orac ...

  6. easyswoole数据库连接池_easyswoole redis连接池:集群迁移教程

    场景 在业务量小的情况下,我们使用Redis单机连接池就可以满足业务需求.因此,redis单机连接池就可以满足我们的业务.因此我们会这样写: 示例 注册连接池 use EasySwoole\Redis ...

  7. c#.net配置mysql数据库连接池_C#MySQL连接池

    我正在使用C#多线程应用程序并使用 MySQL与整个应用程序的单一连接.但是当两个或多个线程同时尝试访问数据库时,我得到以下错误: There is already an open DataReade ...

  8. jdbc如何使用oracle数据库连接池,使用JDBC连接池技术连接Oracle数据库

    在使用JDBC连接数据库要用到两个jar包 1.编写配置文件 #驱动地址 driverClassName=oracle.jdbc.OracleDriver #连接地址 url=jdbc:oracle: ...

  9. [原创]java WEB学习笔记80:Hibernate学习之路--- hibernate配置文件:JDBC 连接属性,C3P0 数据库连接池属性等...

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

最新文章

  1. 堆,栈,内存泄露,内存溢出介绍
  2. HDU 4539郑厂长系列故事――排兵布阵(状压DP)
  3. 2018美团笔试字符串问题
  4. 腾讯V265编码器:给用户以完备的265体验
  5. php更新svn,利用php进行svn更新的php代码及php执行svn更新注意事项
  6. Windows下配置Mysql免安装版
  7. grunt安装与运行
  8. Eclipse 导入项目到git@osc中
  9. Each interface on the back of the fuselage
  10. c++ 结构体和类的区别
  11. 城市ai大脑_激发AI研究的大脑五个功能
  12. winxp netbeui install
  13. de4dot命令 v2.0.3.3405 破解命令
  14. zooKeeper篇-zk的选举机制
  15. AIX 5300-06-01 + Oracle 9.2.0.6 = ORA-27061
  16. 《旅行青蛙》的代码揭秘,攻略,体验
  17. python小案例程序安徽工程大学专用百词斩(刚接触python不喜勿喷)
  18. 通过CSS3的hover一个元素使其兄弟元素也相应改变某种属性
  19. 山东科技大学计算机系招生,山东科技大学在职研究生计算机技术招生动态
  20. .net的反射技术(2)深究及 性能比较

热门文章

  1. linux卸载openjdk_Linux系列(七)——linux其他指令【rpm、yum、sudo】
  2. java什么是类和对象,Java类和对象的概念
  3. dataframe 一列的不同值_python数据分析包|Pandas-02之缺失值(NA)处理
  4. zbar扫描无法近距离扫码_生意好时最怕收银出故障,这几个扫码枪的常见问题你一定要知道...
  5. python处理字典的方法_python字典的常用操作方法小结
  6. java逸出_Java并发编程 - 对象的共享
  7. c语言basic解释器,要理解解释器,做一个小解释器----小话c语言(20)
  8. mysql报11004_使用mysqli扩展技术查看服务器连接错误报告的方法
  9. linux从源码编译软件,linux软件源码的编译安装
  10. 安卓第一行代码第3版pdf_SPECFEM2D用户手册——第3章 网格生成——3.1 如何使用SPECFEM2D...