-
El tiempo de respuesta del sistema se retrasa, lo que afecta la experiencia del usuario -
El aumento en el uso de recursos aumenta la carga en el sistema y el tiempo de respuesta de otras solicitudes también puede verse afectado. -
SQL lento tarda mucho en ocupar la conexión de la base de datos. Si se ejecuta una gran cantidad de consultas SQL lentas al mismo tiempo, puede hacer que todas las conexiones en el grupo de conexiones de la base de datos estén ocupadas, lo que provocará problemas como la conexión de datos. el grupo se llena y el búfer se desborda, lo que hace que la base de datos no pueda responder a otras solicitudes. -
También puede causar problemas como una mayor competencia de bloqueos e inconsistencia de datos.
-
La falta de índices/los índices que no surten efecto darán lugar a un escaneo completo de la tabla de la base de datos, lo que provocará un gran consumo de E/S y un SQL lento. -
Si la cantidad de datos en una sola tabla es demasiado grande, el efecto de la indexación no será lo suficientemente obvio. -
Las declaraciones SQL escritas incorrectamente, como demasiadas uniones o subconsultas, demasiados elementos, limitan los problemas de paginación profunda, el orden provocando la clasificación de archivos, el grupo mediante el uso de tablas temporales, etc. -
La base de datos está limpiando "páginas sucias" y el registro de rehacer está lleno, lo que provoca que todas las actualizaciones del sistema se bloqueen y no se puedan escribir. -
Al ejecutar SQL, si encuentra un bloqueo de tabla o de fila, solo puede esperar a que se libere el bloqueo, lo que resulta en un SQL lento.
Cómo descubrir SQL lento y SQL de alto riesgo
▐Descubra SQL lento
对于外部用户,可以在数据库配置中启用慢查询日志功能,数据库会将执行时间超过一定阈值的慢SQL语句记录到日志中,也可以方便地获取慢查询日志。或者使用其他的数据库性能监控工具、SQL性能分析工具等。
▐ 发现全量SQL
除了执行时长超过1s的慢SQL之外,我们还额外关注了未来可能劣化的慢SQL,这样就需要获取全量SQL,再对其进行分析,筛选出其中风险较大的SQL。我们采取了如下方法:
基于JVM Sandbox进行SQL流水记录的采集
关于JVM Sandbox:「JVM-Sandbox提供动态增强你所指定的类,获取你想要的参数和行信息;提供动态可插拔容器,管理基于JVM-Sandbox的模块。」
简单来说,JVM Sandbox可以动态地将你要实现的代码模板打包编织到目标代码中,实现事件的监听、切入与代码增强。将目标代码的Java方法的调用分解为BEFORE、RETURN和THROWS三个环节,由此在三个环节上引申出对应环节的事件探测和流程控制机制。不仅如此,还有Line事件,可以完成代码行的记录。
// BEFORE-EVENT
try {
/*
* do something...
*/
//LINE-EVENT
a();
// RETURN-EVENT
return;
} catch (Throwable cause) {
// THROWS-EVENT
}
jvm-sandbox-repeater是JVM-sandbox生态体系下的重要模块,具备了JVM-Sandbox所有特点, 封装请求录制/回放基础协议,也提供了通用可拓展的丰富API。
repeator模块可以无侵入式地录制HTTP/Java/Dubbo入参/返回值,业务系统无感知。基于这个能力,我们可以方便的采集和SQL执行相关的Java方法参数以及返回值。通过配置采集点,来采集执行sql的java代码的相关方法、参数和返回值,辅助实现sql采集功能。
jvm-sandbox-repeater 地址:https://github.com/alibaba/jvm-sandbox-repeater?spm=ata.21736010.0.0.3e5975362i3rJi
确认采集点
根据对MyBatis源码分析,我们确认了如下采集点:
JVMSandbox完成数据采集后,通过发送metaq消息的方式,与系统进行对话。对于不同种类的采集消息,我们通过不同的字段加以匹配,最终可以获得每一条SQL流水对应的SQL文本、执行时长、sql参数、db名称、ip端口、sql_mapper资源文件等全部信息,具体如图所示:
以上可以采集到应用的全部SQL,量级是很大的。我们采用了Blink创建时间窗口,进行数据聚合,实时数据处理,减少回流的在线数据量,在此就不展开说明了。
▐ 如何识别高危SQL
根据历史慢SQL治理经验,我们把高危SQL分为以下几类:
不符合集团SQL规约的SQL,可能会埋坑,造成线上问题,影响执行效率等。
通过对SQL语句分析,发现SQL索引使用不当、造成全表扫描,或者SQL扫描行数过多、出现文件排序等。这种SQL即使当前不是慢SQL,随着表数据量的膨胀,未来也可能发展为慢SQL。
SQL执行时间过长,比较容易理解。对慢SQL来说,执行时间越长,风险越高。
SQL规约
集团重点强制SQL规约如下:
【强制】不要使用count(列名)或count(常量)来替代count(*),count(*)就是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。
【强制】count(distinct col) 计算该列除NULL之外的不重复数量。注意 count(distinct col1, col2) 如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。
【强制】当某一列的值全是NULL时,count(col)的返回结果为0,但sum(col)的返回结果为NULL,因此使用sum()时需注意NPE问题。
【强制】使用ISNULL()来判断是否为NULL值。
【强制】对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名(或表名)进行限定。
【强制】在代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句。
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
【强制】IDB数据订正(特别是删除或修改记录操作)时,要先select,避免出现误删除,确认无误才能提交执行。
我们使用了Druid SQL Parser进行SQL解析,Druid SQL Parser是阿里巴巴的开源项目,可以将SQL语句解析为语法树,可以解析SQL的各个部分,如SELECT语句、FROM语、WHERE语句等,并且可以方便获取SQL语句的结构信息,如表名、列名、操作符等。通过分析SQL,可以轻松判断SQL是否符合规约。
SQL索引
返回结果解析:
我们重点关注的点如下:
使用全表扫描,性能最差,即type="ALL"
扫描行数过多,即rows>阈值
查询时使用了排序操作,也比较耗时,即Extra包含"Using filesort"
索引类型为index,代表全盘扫描了索引的数据,Extra信息为Using where,代表要搜索的列没有被索引覆盖,需要回表,性能较差。
以上几点都可能造成SQL性能的劣化,是我们需要额外关注的高风险sql。
作为横向的数据安全治理团队,为了对大淘宝技术部门进行慢SQL治理,我们建立了统一的问题发现-追踪-治理机制。慢SQL治理中涵盖了生产环境、开发环境的慢SQL,区别在于:生产环境中为已经上线的存量慢SQL,开发环境中为新引入的慢SQL,对开发环境引入的慢SQL,修复代价要小于生产环境。接下来分别介绍。
▐ 存量慢SQL治理
在慢SQL推动治理方面,高危慢SQL,会建立Issue持续追踪,Issue存在超期时间,超期后会影响团队健康分。另外,提供应用维度、部门维度的整体慢SQL风险大盘以及排名,针对重点业务、慢SQL高发团队等,进行集中的推进治理。
▐ 增量慢SQL治理
我们希望增量慢SQL能在上线前得到解决,即分支内不要引入慢SQL或者风险SQL,所以结合3.2和3.3,我们建立了开发环境下增量慢SQL发现机制,并建立发布前卡点能力。整体流程如下:
增量慢SQL的修复代价是小于存量慢SQL的,因此这里我们添加了分支定位的能力。同一应用存在多个同学共同开发的情况,有效的分支定位,可以准确指派慢SQL引入人,实现快速推动治理。这里以git上代码改动为切入点,完成了引入慢SQL的sql_map与修改人之间的关系映射,大致逻辑如下:
a. 监听应用部署消息
b. 获取应用信息,拿到git地址
c. 将本次部署分支与master分支做分支diff
d. 解析sql_map文件,获取本次修改的sql内容
e. 记录被修改sql_id与分支的对应关系
f. 根据sql_id查询对应分支
……
这样就可以精准匹配到增量SQL的引入分支,从而指派到开发者,实现了定向问题指派和追踪,并且可以方便完成分支发布前的管控能力。如果存在增量慢SQL,分支发布,合并到master之前,会触发卡点,需要问题解决才能发布。
▐ 安全生产环境慢SQL治理
安全生产环境(SPE环境),是集团层面为保障线上稳定性的灰度流量生产环境,安全生产环境执行过的慢SQL,在线上流量放大后,可能会对DB造成过大的压力。我们额外新增了安全生产环境慢SQL的管控,作为开发环境下SQL被引入到线上的最后一道防线。
整体方案与上面慢SQL治理方案类似,在此就不赘述了。
团队介绍
若你对我们的工作内容感兴趣,欢迎加入挑战,简历(研发、前端、测开)投递邮箱:[email protected]
本文分享自微信公众号 - 大淘宝技术(AlibabaMTT)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。