背景

大促备战,最大的隐患项之一就是慢sql,带来的破坏性最大,也是日常工作中常常带来整个利用抖动的最大隐患,而且对sql好坏的评估有肯定的技术要求,有一些缺乏经验或者因为不够认真造成一个坏的sql胜利走到了线上,等发现的时候要么是造成了线上影响、报警、或者后置的慢sql采集发现,这时候个别无奈疾速止损,须要批改代码上线、或者调整数据库索引。

外围痛点:

1、无奈提前发现慢sql,可能好转为慢sql的语句

2、线上呈现慢sql后,无奈疾速止损

解决思路

1、把问题解决在上线之前,最好的方法就是在测试阶段,甚至在开发阶段就发现一个sql的好坏

2、线上发现慢sql后除了改代码上线、调整数据库表索引的形式外,反对热更新的形式替换sql语句

部门外部,目前大部分数据库框架采纳的mybatis,而后基于mybatis自身的实现机制中,开发一个mybatis组件,能够主动对运行的sql进行提取和剖析,定制一套默认的剖析规定,让sql在开发环境和测试环境执行的时候,就可能做初步的评估,把有问题的慢sql在这个阶段裸露进去;同时具备sql替换性能,在线上呈现问题sql的时候,能够通过ducc配置疾速实现对一个sql的在线替换,大大降低线上问题的止损工夫。

开源计划调研

目前,支流的sql剖析组件,外围性能次要放在了两个方向:1、慢sql的剖析和优化倡议 2、sql的优化重写性能,而且次要偏运维的辅助性能无奈做到无侵入的和利用代码进行集成。也就无奈实现咱们的外围痛点,慢sql提前剖析预警和动静sql替换。

[]()

设计方案

外围性能:SQL剖析预警能力、SQL替换能力

[]()

具体设计

次要分为8个功能模块

模块一:core 次要负责组件的接入到mybatis,以及其它模块的编排调用

模块二:config 次要负责组件配置信息的初始化

模块三:extrat 次要通过解析mybatis 相干对象,提取残缺的待执行sql

模块四:analysis 次要拼接剖析语句,执行explain剖析语句并获取剖析后果

模块五:rule sql剖析规定的加载和初始化,反对自定义规定

目前默认规定(继续扩大):

1、查问未匹配索引

2、匹配索引过滤成果较差

3、返回行数过多

4、应用了文件排序

模块六:score 基于剖析后果和配置的评分规定进行匹配打分,优化倡议组装

模块七:out 输出模块,对于输入后果进行输入,目前已error日志、MQ两种输入形式

模块八:replace替换模块,能够对sql语句基于ducc配置进行动静替换

应用办法

1、引入依赖jar包

<dependency>    <groupId>com.jd.sql.analysis</groupId>    <artifactId>sql-analysis</artifactId>    <version>1.2-SNAPSHOT</version></dependency>

2、配置组件xml

<configuration>    <plugins>        <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" >            <!-- 开启sql剖析性能最简配置 -->            <property name="analysisSwitch" value="true"/>            <!-- 开启sql替换性能最简配置 -->            <property name="sqlReplaceModelSwitch" value="true"/>            <property name="duccAppName" value="workbench-backend"/>            <property name="duccUri" value="ucc://workbench-backend:2d6991cb865f4e6bac6c3e1cf7794cdf@test.ducc.jd.local/v1/namespace/workbench_backend/config/default/profiles/test?longPolling=60000&necessary=false"/>            <property name="duccMonitorKey" value="refundBugFlag"/>        </plugin>    </plugins></configuration>

3、外围配置项

属性用处是否必填默认值备注
analysisSwitch是否开启剖析性能false
onlyCheckOnce是否对一个sqlid只剖析一次true
checkInterval每个sqlid剖析距离300000毫秒onlyCheckOnce 为false才失效
exceptSqlIds须要过滤不剖析的sqlid
sqlType剖析的sql类型默认select、update反对
scoreRuleLoadClass评分规定加载器,用于扩大自定义规定
outModel默认输入形式默认值:LOG反对LOG、MQ两种形式
outputClass评分后果输入类,用于扩大自定义后果输入形式
sqlReplaceModelSwitchsql替换模块是否开启默认 false
duccAppNameducc配置的利用名称(jdos)
duccUriducc uri配置
duccMonitorKeysql替换配置文件对应的key

4、默认剖析成果展现

4.1、慢sql剖析成果

[]()

4.2、sql动静替换成果

5、实际应用计划

5.1、慢sql剖析-日志输入+关键词告警

<configuration>    <plugins>        <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" >            <property name="analysisSwitch" value="true"/>        </plugin>    </plugins></configuration>

5.2、慢sql剖析-日志输入+mq输入+es存储+Kibana剖析

<configuration>    <plugins>        <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" >            <property name="appName" value="workbench-backend"/>            <property name="analysisSwitch" value="true"/>            <property name="outputModel" value="mq"/>            <property name="mqApp" value="qlstation"/>            <property name="mqUser" value="qlstation"/>            <property name="mqPassword" value="D1BCC547"/>            <property name="mqAddress" value="jmq-testcluster.jd.local:50088"/>            <property name="mqTopic" value="jdl_kds_key_node_log"/>        </plugin>    </plugins></configuration>

最终成果

[]()

5.3、慢sql替换-ducc配置动静更新sql语句

<configuration>    <plugins>        <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" >            <property name="sqlReplaceModelSwitch" value="true"/>            <property name="duccAppName" value="workbench-backend"/>            <property name="duccUri" value="ucc://workbench-backend:2d6991cb865f4e6bac6c3e1cf7794cdf@test.ducc.jd.local/v1/namespace/workbench_backend/config/default/profiles/test?longPolling=60000&necessary=false"/>            <property name="duccMonitorKey" value="sqlReplaceConfig"/>        </plugin>    </plugins></configuration>

发现慢sql

[]()

ducc配置

[]()

线上sql被动静替换

[]()

留神:性能正式修复后,需去掉该配置,该性能仅供给急解决线上问题,不倡议作为性能长期应用

性能测试

测试环境千次一般sql查问,每种场景进行了5次测试

未启用插件耗时:11108ms,10237ms,9482ms,7938ms,8196ms

开启sql剖析耗时:16619ms,17333ms,16321ms,19057ms,18164ms

理论配置,只有首次执行或者间隔时间执行,单次影响10ms左右)

开启sql替换耗时:10642ms,8803ms,8353ms,8830ms,9170ms

根本无影响

实用场景

1、慢sql预防

2、线上问题止损

劣势

1、外围劣势:执行时剖析sql,区别于传统的依赖sql执行耗时来评估慢sql,间接基于语法和索引进行前置剖析,不仅能预防某些坏sql在上线后发现是慢sql,还能给出sql优化倡议,能够大限度的防止线上产生慢sql。反对动静对线上sql进行替换,能够对线上问题疾速止损。

2、性能:基于性能和不同的应用场景思考,反对定制化配置,每个sql是否仅进行一次查看、或者按某个工夫距离进行配置。sql替换简直无损耗。

3、扩大:基于后续sql评分规定的扩大、以及剖析后果以不同的形式输入的思考,反对评分规定、输入形式的自定义扩大。

4、老本:接入成本低,无代码侵入。

作者:京东物流 扈海涛

起源:京东云开发者社区