简介: 针对数据库链接池到DRDS链接探活的优化
========数据库
近期在给某专有云客户进⾏云产品应⽤性能优化分析时,发现了⼀个有趣的关于DRDS使⽤层⾯的问题,这⾥给⼤家分享⼀下。
使⽤过DRDS产品的同窗都知道在DRDS中,未分库分表的数据表会存储在“0号库”上,对于这些表操做的SQL会被分发到“0号库”上执⾏。因此⼀般状况下,0号库所在实例的压⼒会⽐其它实例的压⼒稍⼤⼀些。近期分析该客户的数据库性能时,发现客户使⽤的DRDS下0号库所在的RDS实例的压⼒明显⽐其它RDS实例⾼出许多。后端
图1:SQL语句平均每秒执行次数及事务数性能优化
========性能
经过查看0号库所在的RDS实例的执⾏SQL发现,有⼤量的 SELECT 'x' 的查询语句。检查应⽤侧代码后发现,这个查询语句是应⽤侧链接池配置的链接探活SQL,全部的链接池实现⼏乎都有这个功能,能够经过探活SQL检测链接当前是否可⽤。
那么问题来了:优化
答案⼀定是有⽤的,由于若是因⽹络闪断或其它缘由致使的链接状态不可⽤,即便获取到了链接对象,也不能进⾏数据访问操做。因此这个检测是有必要的,但对于使⽤DRDS做为数据源的场景来讲,⽬前配置的检测⽅式是存在问题的。
对于传统的数据库使⽤⽅式,客户端是直接链接到底层数据库的,以下图。探活SQL是直接发到链接的数据库执⾏,这种场景下使⽤ SELECT 'x' 检测客户端到数据库的链接是没有问题的。ui
图2:客户端链接到数据库阿里云
⽽对于使⽤DRDS做为数据源的场景来讲,探活语句在发送到DRDS服务后,会被转发到0号库执⾏,这就意味着这个探活SQL实际上检测的是客户端-->DRDS-->0号库的链路是否正常。spa
图3:客户端经过DRDS链接到数据库线程
这⼀点能够从DRDS上看 SELECT 'x' 的执⾏计划获得证明,以下:对象
图4:执⾏结果1
实际上,这样的数据源链接检测是没有意义的。由于:
========
明⽩以上内容后,咱们解决问题的⽅案就⽐较清楚了,实际上咱们只须要让客户端链接池检测客户端到DRDS的链接状态便可。那有没有这样的检测⽅法呢?
答案固然是有的,通过与DRDS研发同窗确认,将探活SQL修改成 SELECT 'x' FROM dual 便可。
修改后,再次在DRDS查看执⾏计划,以下:
图5:执⾏结果2
在应⽤侧修改链接池的探活SQL配置后,从0号库所在实例上看,已经看不到探活SQL的执⾏记录,⽽且从修改前和修改后0号库所在实例的压⼒来看,效果也⽐较明显,0号库的压⼒相⽐以前降低了⼤概80%左右。
图6:SQL语句平均每秒执行次数及事务数2
⾄此,0号库压⼒过⾼的问题解决了,下⾯咱们聊聊为何会有⼤量的探活语句出现。
探活机制其实是数据源链接池通⽤的⼀种检测机制,能够检测链接池内的链接对象是否真的可⽤。拿Druid链接池举例,探活SQL是经过数据源的 validationQuery 属性配置的。与之相关的配置属性还有:testOnBorrow testWhileIdle testOnReturn timeBetweenEvictionRunsMillis minEvictableIdleTimeMillis。
官⽅解释以下:
⽂章前⾯描述的出现⼤量探活SQL的状况是由于应⽤将链接池的testOnBorrow设置成了true,因此在每次应⽤获取链接时,都会执⾏ validationQuery 配置的探活语句检测链接是否有效。虽然经过前⾯的优化步骤,已经下降了0号库的压⼒,使探活语句不下发到0号库执⾏。
但探活语句仍会在DRDS实例上执⾏,DRDS实例的压⼒并未减轻。经过上⾯对Druid数据源属性配置的说明能够了解到,若是将 testOnBorrow 或 testOnReturn 打开,会对系统性能有⼀定的影响,由于每次都会在获取链接时多执⾏⼀次查询来检测链接是否可⽤。所以推荐使⽤以下的配置:
这样设置完成后,只有在获取到“空闲链接”时,才会进⾏探活检测,⼤⼤下降了业务⾼峰时段的探活频率。同时,也可经过适当缩短minEvictableIdleTimeMillis 的值,兼顾因为⽹络闪断或其它缘由致使的链接不可⽤的状况,减小业务出错的几率,在系统性能和可⽤性之间找到⼀个平衡点。
做者:刘维
原文连接 本文为阿里云原创内容,未经容许不得转载