纯干货:数据库连接耗时慢原因排查

这篇具有很好参考价值的文章主要介绍了纯干货:数据库连接耗时慢原因排查。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

最近公司的社区相关的服务需要优化,由于对业务不熟悉,只能借助监控从一些慢接口开始尝试探索慢的原因。由于社区相关的功能务是公司小程序流量入口,所以相应的服务访问量还是比较高的。针对这类高访问的项目,任何不留神的地方都可能会引起连锁反应导致瓶颈,本次是针对此次排查提供一些我探索的方法。

慢原因

由于我们生产环境接入了阿里云的ARMS监控,所以排查效率会特别高。先列举一些比较常见的慢原因:

  • 下游接口调用慢

这个不多赘述,当时是两个原因:1. 网关慢 2. 代码没有缓存

  • 缓存获取慢

这个是命令使用不规范,使用了redis比较危险的 keys命令,后续此类场景用es代替了

  • 慢SQL

这里也是慢的主力军,比较常见的点:

  1. 索引没命中
  2. 大表之间join关联
  3. 不规范的命令比如:or、not 、like等等
  4. SQL不规范,count后面接limit
  5. 随着数据量的增长,导致平常很快的SQL,突然响应时间飙升

我觉得更多的是前期的表设计存在很大的问题,导致太多的表关联查询效率很差。

  • 获取连接数慢

这里也是我之前比较忽略的地方,也是这次比较关键的点。

连接慢的排查之路

我们使用的是阿里的druid的连接池,所以一开始并没有觉得有什么大问题。

从ARMS中找了一个比较有代表性的图:
纯干货:数据库连接耗时慢原因排查
一共耗时12秒,一开始只觉得应该和并发请求有关,因为只有比较少量的请求会出现该情况。

这是一个查询接口,而且承载了该服务大量的请求。

通过分析链路发现了两个比较明显的问题:

- 下游的接口慢
- SQL比较耗时

嗯,双手插兜,自信回头!烟来~

经过一番优化之后,效果显著,但是还是存在几秒获取连接的情况。

这是啥情况?仔细盯着链路图,发呆了几秒,不对呀!查询接口咋还出现了commit提交事务的命令呢?

由于这个接口查询本地表的SQL并不慢,而且并没有修改数据的动作存在,转而又去看了相应的代码。方法上面也没有加上@Transaction呀?咋就把事务开了呢!思来想去,泥马不会在类上加了吧! 一看果然!!!

@Service
@Transactional(rollbackFor = Exception.class)
public class XxxxService extends AbstractUserService {
}

由于这个接口访问频率非常高,时不时会执行缓慢(有下游和本地资源不稳定的因素),开启了事务就意味着,拿到一个数据库连接之后需要执行完整个事务逻辑才会释放连接
也就是说如果当前时段比较耗时执行了3秒钟,此时并发比较高,你的连接数在这三秒内会急剧上升。
连接数上升了,事务多了,可能还会发生锁争抢,这也就是平常一个SQL你觉得必然不会慢,但它就是莫名其妙的慢了可能导致的原因。

怕了怕了,这种写法会导致接口内部的方法可能都会默认开启事务,一旦事务内部有出现下游调用或者慢操作,就会出现长事务。

此时感觉自己深陷沼泽。。。赶紧写了个工具扫描所有service类上加了@Transaction注解的功能。。逐一修复!!!

优化了一版之后,我想应该差不多了吧!
嗯,双手插兜,转身就走。不恋战~

第二天瞄了一眼,嗯,还是有提升,但是还是有几百毫秒的获取连接情况!
天哪~

又不情不愿的盯着ARMS的各种功能看【不得不说ARMS还是挺全面的】

终于在线程监控中发现端倪:
纯干货:数据库连接耗时慢原因排查
看到这个
at com.alibaba.druid.pool.DruidAbstractDataSource.testConnectionInternal (DruidAbstractDataSource.java:1407)
心里顿时感觉应该和配置有关,通过看源码发现是到了testOnBorrow满足的逻辑,然后去看了服务相关的配置:
spring.datasource.druid.testOnBorrow=true

嗯嗯嗯,去官网上看了相关的解释;

配置 默认值 说明
testOnBorrow true 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testWhileIdle false 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
timeBetweenEvictionRunsMillis 1分钟(1.0.14) 有两个含义:1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明
  • druid github 配置参考
  • druid github 通用配置

想想也是,如果每次获取连接都去校验是否有效,这不纯纯浪费么。通常一般99%的校验都是浪费,倒不如指定的超时时间去校验一次,当然各有取舍,极端情况可能会出现连接时效的问题,但影响应该也不大。

嗯,双手… 放好,战斗还没有结束,多观察几天再看看!

另外再补充一个阿里云的jedis的最佳实践吧

还有一个扫描@Transaction注解的方法:文章来源地址https://www.toymoban.com/news/detail-469008.html

import cn.hutool.core.lang.ClassScanner;
import cn.hutool.core.lang.Filter;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class TransactionPonintCase {
    public static void main(String[] args) {
        List<Class> clazzList= new ArrayList<>();
        List<String> methodList= new ArrayList<>();
        Set<Class<?>> classes = ClassScanner.scanAllPackage("你要扫描的包", new Filter<Class<?>>() {
            @Override
            public boolean accept(Class<?> aClass) {
                boolean annotationPresent = aClass.isAnnotationPresent(Transactional.class);
                if(annotationPresent){
                    clazzList.add(aClass);
                    return true;
                }
                for (Method declaredMethod : aClass.getDeclaredMethods()) {
                    if(declaredMethod.isAnnotationPresent(Transactional.class)){
                        methodList.add(declaredMethod.getDeclaringClass().getName()+"."+declaredMethod.getName());
                    }
                }
                return annotationPresent;
            }
        });

        System.out.println(">>>>>>>>>>>>>>>>> 类级别注解 <<<<<<<<<<<<<<<<<<<<<");

        for (Class<?> aClass : classes) {
            System.out.println(aClass.getName());
        }

        System.out.println(">>>>>>>>>>>>>>>>> 方法級別注解 <<<<<<<<<<<<<<<<<<<<<");

        for (String name : methodList) {
            System.out.println(name);
        }
    }
}

到了这里,关于纯干货:数据库连接耗时慢原因排查的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 耗时6个月,我做了一款干净、免费、开源的AI数据库管理工具

    在消失的这段时间,我和小伙伴们做了一款集成了AI的数据库管理工具Chat2DB。 他是数据库也集成了AIGC的能力,能够将自然语言转换为SQL,也可以将SQL转换为自然语言,还可以给出SQL的优化建议,可以极大提升效率。 GitHub地址:https://github.com/chat2db/chat2db 官网地址:https://ch

    2024年02月13日
    浏览(71)
  • 耗时6个月,我们做了一款干净、免费、开源的AI数据库管理工具

    在消失的这段时间,我和小伙伴们做了一款集成了AI的数据库管理工具Chat2DB。 他是数据库也集成了AIGC的能力,能够将自然语言转换为SQL,也可以将SQL转换为自然语言,还可以给出SQL的优化建议,可以极大提升效率。 GitHub地址:https://github.com/chat2db/chat2db 官网地址:https://ch

    2024年02月13日
    浏览(73)
  • 【虹科干货】逻辑数据库可能已经无法满足需求了!

    不可否认,单个Redis实例已经不能满足实际生产中的需求了。为了解决由此带来的问题,何不试试用专用实例代替逻辑数据库呢? 一、逻辑数据库可能已经无法满足需求的4个迹象 1.您有个“吵闹的邻居” PS:“吵闹的邻居”指同一个Redis OSS实例中其它繁忙的逻辑数据库。

    2024年02月07日
    浏览(56)
  • 【MySQL】数据库排查慢查询、死锁进程排查、预防以及解决方法

    1.1检查慢查询日志是否开启 1.1.1使用命令检查是否开启慢查询日志: 如果是 Value 为 off 则并未开启 1.1.2开启并且查看慢查询日志: MySQL提供了慢查询日志功能,可以记录所有执行时间超过long_query_time秒的查询语句,通过分析这些慢查询可以找到数据库性能瓶颈。 启用慢查询日志

    2024年03月19日
    浏览(91)
  • MySQL数据库干货_16—— SQL99标准中的查询

    SQL99标准中的查询 MySQL5.7 支持部分的SQL99 标准。 SQL99中的交叉连接(CROSS JOIN) 示例: 使用交叉连接查询 employees 表与 departments 表。 SQL99中的自然连接(NATURAL JOIN) 自然连接 连接只能发生在两个表中有相同名字和数据类型的列上。如果列有相同的名字,但数据类型不同,NATURAL J

    2024年02月06日
    浏览(63)
  • Mysql 数据库时间与系统时间不一致问题排查

    在我们学习中使用到sysdate这个函数时,发现查出来的日期时间与当前的正确时间不一致,相差8个小时左右,为什么会产生这个问题?又该如何解决? – 在数据库中使用sysdate()函数查询系统时间 select sysdate(); 结果显示: 原因分析1:第一时间想到的是数据库所在的云服务器时

    2024年02月06日
    浏览(55)
  • MySQL数据库干货_11—— MySQL中的非空约束(Not Null)

    非空约束(Not Null) 添加非空约束 使用DDL语句添加非空约束。 示例: 向 emp 表中的 salary 添加非空约束。 删除非空约束 使用DDL语句删除非空约束。 示例: 删除emp表中salary 的非空约束。 创建表时添加约束 查询表中的约束信息: 示例: 创建 depts 表包含 department_id 该列为主键且

    2024年02月07日
    浏览(54)
  • 必选云原生数据库的原因

     全栈云产品免费领,玩转云原生数据库,点击进入:https://click.aliyun.com/m/1000370368/ 随着云原生的高速发展,打破了企业传统的部署方式,以及开发主线和运维方式。可以说云原生的诞生以及发展,促使了企业的技术变革和进步。作为云原生领域的数据库不仅是非常重要的一

    2023年04月12日
    浏览(44)
  • springboot数据库回滚失败原因

    更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码: https://gitee.com/nbacheng/nbcio-boot 前端代码:https://gitee.com/nbacheng/nbcio-vue.git 在线演示(包括H

    2024年01月24日
    浏览(43)
  • 数据仓库扫盲系列(1):数据仓库诞生原因、基本特点、和数据库的区别

    随着互联网的普及,信息技术已经深入到各行各业,并逐步融入到企业的日常运营中。然而,当前企业在信息化建设过程中遇到了一些困境与挑战。 1、历史数据积存。 过去企业的业务系统往往是在较长时间内建设的,很少进行大面积的改造或者升级,历史数据留存在业务系

    2024年02月08日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包