MySQL的MaxIdleConns不合理,会变成短连接的原因

1 背景

最近石墨文档线上业务出现了一些性能问题,在突发流量情况下,有个业务性能急剧下降。该服务是依赖于数据库的业务,会批量获取数据库里的数据。在经过一系列的排查过程后,发现该服务到数据库的连接数经常超过MaxIdleConns,因此怀疑是数据库的配置导致的性能问题,所以以下针对数据库的代码进行了剖析,并做了相关实验。

2 配置解读

maxIdleCount      int                    // zero means defaultMaxIdleConns; negative means 0
maxOpen      int          // <= 0 means unlimited
maxLifetime    time.Duration     // maximum amount of time a connection may be reused
maxIdleTime       time.Duration          // maximum amount of time a connection may be idle before being closed

可以看到以上四个配置,是我们Go MySQL客户端最重要的配置。

maxIdleCount 最大空闲连接数,默认不配置,是2个最大空闲连接

maxOpen 最大连接数,默认不配置,是不限制最大连接数

maxLifetime 连接最大存活时间

maxIdleTime 空闲连接最大存活时间

3 源码解析

我们的场景是客户端与MySQL建立的连接数经常大于最大空闲连接数,这会导致什么问题?我们看下下图中的源码。

我们可以看到,当最大空闲连接数小于客户端与数据库建立的连接数的时候,那么就会返回false,并且最大连接数关闭计数器加1。

然后上图中,我们就可以看到,连接被关闭了(MySQL源码里也不留点缓冲时间再关闭)。Go的MySQL客户端这个操作,就会导致当突发流量情况下,由于请求量级过大,超过了最大空闲连接数的负载,那么新的连接在放入连接池的时候,会被无情的关闭,变成短连接,导致你的服务性能进一步恶化。

4 实验

4.1 模拟线上并发数大于MaxIdConns情况

测试代码 , 为了检测以上逻辑,假设了以下场景,设置最大连接数为100,最大空闲连接数为1,并发数为10的goroutine来请求数据库。我们通过MySQL的stats的maxIdleClosed的统计,可以看到下图,我们的连接不停的被关闭。

4.2 模拟线上并发数小于MaxIdConns情况

测试代码 ,假设了以下场景,设置最大连接数为100,最大空闲连接数为20,并发数为10的goroutine来请求数据库,可以看到下图中,无MaxIdleClosed的关闭统计。

4.3 抓包验证线上并发数大于MaxIdConns情况

测试代码 ,为了验证没有理解错代码,抓个包最稳妥。我们将main函数里放个select{},程序执行完mysql的语句后,看下tcp状态和抓包数据。

可以发现确实是tcp的状态统计与MySQL客户端的统计是一致的,并且存在fin包。

5 总结

当突发流量情况下,由于请求量级过大,超过了最大空闲连接数的负载,那么新的连接在放入连接池的时候,会被关闭,将连接变成短连接,导致服务性能进一步恶化。为了避免这种情况,下面列举了,可以优化的措施。

提前将maxIdleConns设大,避免出现短连接

做好mysql读写分离

提升mysql的吞吐量:精简返回字段,没必要的字段不要返回,能够够快复用连接

吞吐量的包尽量不要太大,避免分包

优化连接池,当客户端到MySQL的连接数大于最大空闲连接的时候,关闭能够做一下延迟(官方不支持,估计只能自己实现)

读请求的最好不要放MySQL里,尽量放redis里

6 测试代码

https://github.com/gotomicro/test/tree/main/gorm

以上就是MySQL的MaxIdleConns不合理,会变成短连接的原因的详细内容,更多关于MySQL的MaxIdleConns不合理的资料请关注我们其它相关文章!

(0)

相关推荐

  • 解决navicat远程连接mysql报错10038的问题

    navicat远程连接mysql报错10038一般由以下两个原因: 一:本地防火墙问题 在本地安装了mysql.navicat并打开了mysql服务的情况下,来设置防火墙. 首先右击或者点击入站规则,找到新建规则,点击. 点击端口. 在特定本地端口中填入3306. 一直点击下一步. 这里可以给一个好分别的名称即可. 之前再尝试连接即可,若仍然不可以,可能是服务器方面的问题. 二:服务器3306端口未打开 首先需要在安全组开放端口. 我这里使用的是阿里云服务器.首先需要进入云服务器,找到安全组.

  • 使用IDEA配置Tomcat和连接MySQL数据库(JDBC)详细步骤

    IDEA配置Tomcat 1,点击Run-EDit Configurations- 2.点击左侧"+"号,找到Tomcat Server-Local(若是没有找到Tomcat Server 可以点击最后一行 34 items more) 3.在Tomcat Server -> local-> Server -> Application server项目下,点击 Configuration ,找到本地 Tomcat 服务器,再点击 OK按钮. 至此,IntelliJ I

  • 详解DBeaver连接MySQL8以上版本以及解决可能遇到的问题

    数据库MySQL版本8.0.18 下载一个DBeaver.exe 下载地址:https://dbeaver.io/download/ 点击新建 -->数据库连接 -->下一步 选择数据库 -->下一步 -->完成 双击新建的文件会提示下面这样的错误 原因是数据库的时区配置不对 打开cmd以管理员运行 登录数据库 -->输入 show variables like '%time_zone%'; SYSTEM为默认美国时间,解决方法:输入 set global time_zone

  • C#连接MySql数据库的方法

    1.要连接MySql数据库必须首先下载MySql官方的连接.net的文件,文件下载地址为http://dev.mysql.com/downloads/connector/net/6.6.html#downloads ,下载平台选择.Net&Mono,下载ZIP免安装版.2.解压缩刚才下载的mysql-connector-net-6.6.6-noinstall.zip文件,里面有几个版本选择,在这里我选V4, 选中这几个文件,然后添加到C#项目的引用中,然后就可以编写程序进行数据库的操作了. 3.

  • Mysql连接数设置和获取的方法

    获取连接数 --- 获取最大连接数 SHOW VARIABLES LIKE '%max_connections%'; --- 获取连接列表 SHOW PROCESSLIST; --- 获取连接列表 SHOW FULL PROCESSLIST; --- 获取当前的链接信息 Threads_connected是当前的连接数 SHOW STATUS LIKE 'Threads%'; --- 获取连接统计 比如历史最大连接数以及最大连接时长等 SHOW STATUS LIKE '%Connection%

  • 连接docker里面的mysql失败解决方法

    场景:在虚拟机的docker容器中安装latest版本的mysql之后,在宿主机中使用navicat连接虚拟机中的mysql出现下图报错: 2059 : Authentication plugin 'caching_sha2_password' cannot be loaded: 解决办法: 1.首先docker ps命令查看正在运行的容器,确保我们想要连接的mysql已经启动,如果没启动使用docker start命令启动(下图查看结果表示已经启动了一个mysql) 2.接着运行docker

  • Php连接及读取和写入mysql数据库的常用代码

    既然现在你看到了这篇文章,说明你肯定知道PHP和MySQL是怎么一回事,我就不啰嗦了.但为什么你还要继续阅读此文呢?可能是以前你习惯复制粘贴一些代码,并没有真正弄懂代码的含义:也可能你以前弄懂了,但像我一样,有一段时间没有接触,生疏了:再或者,有人问你类似的简单问题,而你已经不屑于回答,直接上网搜索,恰好找到了这篇,于是就推荐给那谁谁谁了... 不管怎样,在这里我总结了常用的PHP连接MySQL数据库以及读取写入数据库的方法,希望能够帮到你,当然也是作为我自己的一个回顾总结. 1.为了更好地设置

  • Navicat Premium远程连接MySQL数据库的方法

    新建连接的一方相当于是客户端,被连接的相当于是服务端,步骤如下: 1.创建子账户,在Navicat查询界面键入以下授权命令,依次执行 GRANT ALL PRIVILEGES ON test.* to 'root333'@"%" IDENTIFIED by 'abc111' WITH GRANT OPTION; FLUSH PRIVILEGES; all PRIVILEGES意思是所有权限: on后面接的是数据库名.表名 如:test.* 的意思是授予的权限是数据库test下的所有表,

  • 浅谈Mysql连接数据库时host和user的匹配规则

    --连接数据库时,host和user的匹配规则 官方文档:https://dev.mysql.com/doc/refman/5.7/en/connection-access.html --host和user的匹配规则如下: --是host为明确的最先匹配,host带%模糊的时候最后匹配,但host为''(空)位于%之后才匹配 --相同的host时候,比较user为明确的最先匹配,user为''(空)最后匹配 --相同的host和user时,排序是不确定的 When multiple matche

  • 远程连接mysql 授权方法详解

    今在服务器上 有mysql 数据库,远程访问,不想公布root账户,所以,创建了demo账户,允许demo账户在任何地方都能访问mysql数据库中shandong库. 方案一: 在安装mysql的机器上运行: 1: 创建user用户 复制代码 代码如下: CREATE USER demo IDENTIFIED BY "123456" 2. 复制代码 代码如下: mysql>GRANT ALL PRIVILEGES ON shandong.* TO 'demo'@'%'WITH G

  • PHP连接MySQL数据库三种实现方法

    引言 PHP与MySQL的连接有三种API接口,分别是:PHP的MySQL扩展 .PHP的mysqli扩展 .PHP数据对象(PDO) ,下面针对以上三种连接方式做下总结,以备在不同场景下选出最优方案. PHP的MySQL扩展是设计开发允许php应用与MySQL数据库交互的早期扩展.MySQL扩展提供了一个面向过程的接口,并且是针对MySQL4.1.3或者更早版本设计的.因此这个扩展虽然可以与MySQL4.1.3或更新的数据库服务端进行交互,但并不支持后期MySQL服务端提供的一些特性.由于太古

随机推荐