一则 TCP 缓存超负荷导致的 MySQL 连接中断的案例分析

这篇具有很好参考价值的文章主要介绍了一则 TCP 缓存超负荷导致的 MySQL 连接中断的案例分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

除了 MySQL 本身之外,如何分析定位其他因素的可能性?

作者:龚唐杰,爱可生 DBA 团队成员,主要负责 MySQL 技术支持,擅长 MySQL、PG、国产数据库。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文约 1200 字,预计阅读需要 3 分钟。

背景

在执行跑批任务的过程中,应用程序遇到了一个问题:部分任务的数据库连接会突然丢失,导致任务无法完成。从数据库的错误日志中,发现了 Aborted connection 的信息,这说明客户端和服务器之间的通信被异常中断了。

分析

为了找出问题的原因,我们首先根据经验,分析了可能导致连接被 Aborted 的几种常见情况:

  1. 客户端没有正确地关闭连接,没有调用 mysql_close() 函数。
  2. 客户端空闲时间超过了 wait_timeoutinteractive_timeout 参数的秒数,服务器自动断开了连接。
  3. 客户端发送或接收的数据包大小超过了 max_allowed_packet 参数的值,导致连接中断。
  4. 客户端试图访问数据库,但没有权限,或者使用了错误的密码,或者连接包不包含正确的信息。

然而,经过排查,发现以上情况都不适用于当前的问题。因为任务在之前都是正常运行的,而且程序也没有变动,所以可以排除第一种情况。查看了 MySQL 的超时参数 wait_timeoutinteractive_timeout ,发现它们都是 28800,也就是 8 个小时,远远超过了任务执行时间,所以可以排除第二种情况。也检查了客户端和服务器的 max_allowed_packet 参数,发现它们都是 64M,也不太可能超过这个限制,所以可以排除第三种情况。我们也确认了客户端的数据库访问权限,密码,连接包等信息,都是正确的,所以可以排除第四种情况。

到此,我们初步感觉 MySQL 层面应该没有问题,问题可能出在其他地方。

为了进一步定位问题,我们尝试了修改服务器的一些相关内核参数,如下:

net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_time = 120
net.core.rmem_default = 2097152
net.core.wmem_default = 2097152
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_syn_backlog = 16384

这些参数主要是为了优化网络连接的性能和稳定性,避免连接被意外关闭或超时。但是,修改后的结果并没有改善,连接还是会异常中断。

最后,我们尝试了进行抓包分析,通过 Wireshark 工具,我们发现了一个异常的现象:服务器会给客户端发送大量的 ACK 包。如下图所示:

一则 TCP 缓存超负荷导致的 MySQL 连接中断的案例分析,mysql,oceanbase,数据库

这些 ACK 包是 TCP 协议中的确认包,表示服务器已经收到了客户端的数据包,请求客户端继续发送数据。但是,为什么服务器会发送这么多的 ACK 包呢?我们猜测可能是网络有异常,导致客户端接收不到服务器返回的 ACK 包,所以服务器会反复发送 ACK 包,直到超时或收到客户端的响应。但是,经过网络人员的排查,未发现有明显的问题。

继续分析抓包,我们又发现了另一个异常的现象:客户端会给发送服务器一些窗口警告。如下图所示:

一则 TCP 缓存超负荷导致的 MySQL 连接中断的案例分析,mysql,oceanbase,数据库

这些窗口警告是 TCP 协议中的流量控制机制,表示服务器或客户端的接收窗口已经满了,不能再接收更多的数据。

[TCP Window Full] 是发送端向接收端发送的一种窗口警告,表示已经到数据接收端的极限了

[TCP ZeroWindow] 是接收端向发送端发送的一种窗口警告,告诉发送者,接收端接收窗口已满,暂时停止发送。

根据以上信息,我们推测出了问题的原因:由于 MySQL 需要发送的数据太大,客户端的 TCP 缓存已经满了,所以需要等待客户端把 TCP 缓存里面的数据消化掉,才能继续接收数据。但是,在这段时间内,MySQL 会一直向客户端请求继续发送数据,如果客户端在一定时间内(默认是 60 秒)没有响应,MySQL 就会认为发送数据超时,中断了连接。

为了验证推测,查看 MySQL 的慢日志,发现了很多 Last_errno: 1161 的记录。

这些记录表示 MySQL 在发送数据时遇到了超时错误,而且发现出现的次数和应用程序失败的任务数很接近。根据 MySQL 官网的说明,这个错误的含义是:

Error number: 1161; Symbol: ER_NET_WRITE_INTERRUPTED; SQLSTATE: 08S01

Message: Got timeout writing communication packets

可知这个表示的意思是网络写入中断,而MySQL层面有个参数就是控制这个的,所以尝试更改net_write_timeout参数为600,跑批任务正常运行。

所以 MySQL 连接被异常中断的原因在于客户端获取的数据库太大,超过了客户端 TCP 缓存,客户端需要先处理缓存中的数据,在这段时间内,MySQL 会一直向客户端请求继续发送数据,但是客户端 60 秒内一直未能响应,导致 MySQL 发送数据超时,中断了连接。

结论

通过上述的分析和尝试,我们得出了以下的结论:

  • 抓包信息中,有很多 ACK 信息是因为客户端的缓存满了不能及时给服务端反馈,所以服务器会反复发送 ACK 信息,直到超过 60秒(net_write_timeout 默认值是 60),导致 MySQL 把连接中断了。
  • 慢日志中,有很多 Last_errno: 1161 的记录,是因为该 SQL 实际已经在 MySQL 中执行完毕了,但是在发送数据到客户端时,由于数据量太大超过了客户端的 TCP 缓存,然后客户端上的应用在 60 秒内未把缓存中的数据处理掉,导致 MySQL 往客户端发送数据超时。
  • MySQL 层面调整 net_write_timeout 参数只能缓解这个现象,根因在于单个 SQL 获取的数据量太大,超过了客户端的缓存大小,应用程序不能短时间内处理完缓存中的数据,进而导致后续的数据发送超时。

优化建议

  • 业务层面进行分批处理数据,避免单个 SQL 从服务器获取大量的数据,导致客户端的 TCP 缓存不足。
  • 提高 MySQL 中的 net_write_timeout 参数或者增加客户端的 TCP 缓存,可缓解此情况的发生,但不能彻底解决该问题,因为数据量太大仍然会影响性能和稳定性。
  • 优化 SQL 语句,减少不必要的数据返回,比如使用 LIMIT、WHERE 等条件,或者使用聚合函数,分组函数等,以减少数据量和提高查询效率。

更多技术文章,请访问:https://opensource.actionsky.com/

关于 SQLE

SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。文章来源地址https://www.toymoban.com/news/detail-860530.html

SQLE 获取

类型 地址
版本库 https://github.com/actiontech/sqle
文档 https://actiontech.github.io/sqle-docs/
发布信息 https://github.com/actiontech/sqle/releases
数据审核插件开发文档 https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse

到了这里,关于一则 TCP 缓存超负荷导致的 MySQL 连接中断的案例分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 虚拟交换缓存不足导致qt编译失败

    qt pro make 失败: virtual memory exhausted: Cannot allocate memory 查看内存: 设置交换缓存: 释放缓存 开机自动使用该虚拟内存的启动脚本 参考

    2024年02月10日
    浏览(47)
  • Android studio 通过mysql连接数据库完成注册登录,登陆后通过tcp协议与电脑的网络调试助手互发信息

    先不多直接看软件截图 这个是首页等陆界面 xml代码如下 MainActivity文件    注册界面的xlm文件  这个界面比较简单就不介绍了   MainActivity文件 这是一个注册失败的界面,如果数据库内有相同的账号密码则显示注册失败 话不多说直接上代码 MainActivity里面的代码 这里是user类用

    2024年02月02日
    浏览(49)
  • Tomcat 的 work 目录缓存导致的JSP页面图片更新问题

    一、问题分析 1. 修改后重新部署没有变化     笔者之前部署了一个后台管理项目,通过它来发布课程内容,其中有一个 JSP 课程页面,在该 JSP 页面里也引用了类文件 Constant.java 里的一个变量(ALIYUN_OSS_PATH),该变量的值是一个域名地址( static.aaa.com ),在该 JSP 页面基于

    2024年02月02日
    浏览(40)
  • python中使用selenium进行爬虫时,导致(内存已缓存)备用内存占用过大导致崩溃问题,3个解决方案

    在使用python进行爬虫的时候,使用selenium进行爬取的时候经常会出现已缓存过大的情况,如果缓存出现过大之后再次执行的话就会计算机拒绝,但是这个时候我们的内存又有很多空间可以使用,一开始我以为是占用文件过多然后点360的那个进行文件整理和清理垃圾,结果效果

    2023年04月08日
    浏览(53)
  • 【算法一则】编辑距离 【动态规划】

    给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。 你可以对一个单词进行如下三种操作: 插入一个字符 删除一个字符 替换一个字符 这个问题可以使用动态规划来解决。我们可以定义一个二维数组dp,其中dp[i][j]表示将word1的前i个字符转换成word

    2024年04月24日
    浏览(36)
  • rocketmq客户端本地日志文件过大调整配置(导致pod缓存cache过高)

            在使用rocketmq时,发现本地项目中文件越来越大,查找发现在/home/root/logs/rocketmqlog目录下存在大量rocketmq_client.log日志文件。 开启slf4j日志模式,在项目启动项中增加-Drocketmq.client.logUseSlf4j=true 因为配置使用的是System.getProperty获取,所以只能使用系统环境配置。 调整日

    2024年02月15日
    浏览(41)
  • 织梦栏目有缓存导致刚发布的文章条数和分页不同步处理方法

    刚做一个网站需要大量填充数据,发觉得新增的数据没有即时同步到栏目文章分页里 如图: 图2: 分页对不上,经查,由于缓存问题要等1个小时可以自动变正常,或手工用ftp把data》cache里所有文件清空,也可以解决,如果不想每次都手工清理,可以通过改文件,使之不用缓

    2024年02月02日
    浏览(57)
  • K8S容器的一则故障记录

       kubelet 、pod持久化 metrics/vlalphal容器 kube-controller、apiserver     XXX反馈说某某业务服务异常,无法启动,需要进行协助排查。经常会接到这样一个需求,一开始无法清楚知道具体什么问题,需要跟一线运维人员详细做沟通,了解故障问题的细节。     根据一线运维人

    2024年02月02日
    浏览(48)
  • tcp缓存引起的日志丢失

    logstash从数据源拉取日志,然后通过tcp插件发送到proxy进程中。在业务侧发现日志量明显少了,所以有了这一次的问题排查。 首先从logstash侧开始检查。我们先看logstash的日志,没有明显的报错信息。 然后再查看logstash管道的状态。可以很明显的看到,在output管道中,in远远大

    2024年01月24日
    浏览(27)
  • 项目引入多个连接池,导致使用其他连接池,maven分析学习

    第一步在命令行中执行 如果你的settings文件不是项目使用的setting配置,那么就使用下面的命令 然后打开这个输出的 excludeParentstart.log文件 然后得到了一堆密密麻麻的文件 这个玩意怎么看呢?我们得先知道依赖加载顺序 执行命令 mvn dependency:tree 会输出Maven项目的依赖树,展示

    2024年02月11日
    浏览(40)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包