前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于MySQL | 这个问题100个人都没搞懂

关于MySQL | 这个问题100个人都没搞懂

作者头像
腾讯云数据库 TencentDB
发布2019-05-16 15:01:21
8410
发布2019-05-16 15:01:21
举报
文章被收录于专栏:腾讯云数据库(TencentDB)

点击上方蓝字每天学习数据库

作者简介:鲁越,腾讯云数据库架构师,主要负责腾讯云数据库MySQL、Redis、MongoDB、Oracle等数据库架构设计、数据库运维、运营开发等工作,曾就职于网易游戏。


问题背景

用户将MySQL从IDC迁移至公有云后,时常有出现建立连接超时的情况,业务使用的场景是PHP短连接到MySQL,每秒的新建连接数在3000个左右,这个量算是比较大。但在IDC内自建时也是这样的使用场景,从未遇到过这个问题。

排查步骤

1、首先肯定是排查MySQL以及MySQL所在的物理机是否有异常,排查了一圈之后,发现数据库的慢查询基本没有,数据库和物理机的负载都不算高,基本可以排除是数据库本身的问题。

2、超时问题最容易联想到的就是网络上有异常,在物理机上抓包后,抓到在有问题的时间点确实有SYN包的重传。

3、仔细排查这个异常的流,发现重传并不是因为没有收到包或者发出去了包没有响应,那么说明问题并不是出现在网络链路上。这个流中,客户端首先发了一个SYN包给服务器,奇怪的是,服务器在收到这个SYN包过后,并没有按照TCP三次握手的方式回复一个SYN+ACK,而是回复了一个普通的ACK,而且这个ACK回复的seq并不是SYN包的seq 0,而是一个比较奇怪的数字706168360。

4、另外,在物理机上netstat发现,有大量的连接处于TIME_WAIT状态。

5、那这里就产生了两个疑点:

1)为什么Server端会有大量的连接进入TIME_WAIT状态?

2)为什么Server端没有正常回复SYN+ACK,而是回复了一个普通的ACK?

6、要解释第一个问题,我们先来回顾一下TCP四次挥手的流程

从流程里面我们看到,进入TIME_WAIT状态是先发送FIN包的一方,也就是主动断开连接的一方。一般来说,客户端连接服务器,如果没有什么异常,连接是会由客户端主动断开的。那这里为什么服务器上面会有大量的连接处于TIME_WAIT状态?难道这个场景下连接是服务器主动断开的?

我们来看看一个程序跟MySQL通信的一个常规过程,程序首先跟MySQL建连,建连完成之后执行SQL请求进行数据通信,通信完成后,会发送一个quit命令给MySQL服务器断开连接。这个流程看似没有什么疑点,但重点就在这个quit命令上面。我们考虑一下MySQL服务器在收到这个quit请求后会做一些什么处理。

首先肯定是处理应用层的一些连接相关的信息。处理完成之后,再处理网络层的连接。 网络层的连接怎么处理呢?等客户端发送FIN包过来吗?要是客户端一直不发怎么办呢?其实这里我们不难找到答案,也很容易猜想出MySQL的处理方式:主动发送FIN包来断开这个TCP连接。 这个也就解释了为什么大量进入TIME_WAIT状态的是MySQL服务器而不是客户端。不仅仅是MySQL,包括redis、mongodb等会接受到类似quit命令退出的数据库产品,也都是相似的处理方式。

7、第一个问题解释清楚了, 我们再来看看第二个,为什么服务器没有正常的回复SYN+ACK。

首先,我们知道,linux下连接进入TIME_WAIT状态的时间是2个MSL,也就是120秒。在每秒3000个短连接的情况下,120秒内可以产生大约36万个进入TIME_WAIT状态的连接。而客户端可以使用的总端口数是65536,除去一些系统固定分配的,差不多也就60000个左右。假如这3000个每秒的短连接都是由一台客户端连接过来的,那20秒的时间就会复用到之前已经使用过的端口,这个时候该端口对应在服务器端的连接还在TIME_WAIT状态。所以服务器在收到新连接的SYN包后,并不认为这是一个新建连接请求的SYN包过来,而是把它当做一个普通数据包来处理,所以回复了一个普通的ACK和一个较大的seq。其实这个seq就是上一次连接的最后一个seq。

8、排查到这里,这个问题的处理思路就比较明确了, 就是减少服务器上进入TIME_WAIT状态的连接数量,首先想到的当然是开启time_wait的快速回收。但在实际开启后,我们发现快速回收并没有生效, 这里又涉及到另一个问题:

开启time_wait快速回收需要开启net.ipv4.tcp_timestamps,但是这个参数在有nat网关的环境下开启会导致连接异常,云上vpcgw层会在接受到带有timestamps包后把这个字段去掉,导致了即使开启了快速回收也没有实际生效。这里也解释了为什么客户在自建IDC内没有问题而迁移到云上之后开始出问题。

解决方案

1、客户端改用长连接

需要客户端的改动比较大,但能彻底解决问题,高并发的场景下,长连接的性能也明显好于短连接。

2、增加客户端的个数,避免在2MSL时间内使用到重复的端口

能够降低出问题概率,但需要增加成本,性价比不高。

3、降低net.ipv4.tcp_max_tw_buckets(有风险)

能够降低出问题概率,降低的程度视修改的参数值而定,设置为0可以完全解决。此方法在网络状况不好的情况下有风险,一般内网低延迟的网络风险不大。

4、客户端在断开连接时,不用quit的方式退出,直接发FIN或者RST

能够彻底解决问题,需要修改客户端底层库,有一定风险。

5、修改linux内核减小MSL时间

能够降低出问题的概率,需要修改linux内核,难度和风险都较大。

往期推荐

《迪B课堂:MySQL概览》

《迪B课堂:导致MySQL主从复制延迟的原因》

免费试用

包括云数据库MySQL在内的40+款热门云产品,实名认证的企业用户可免费试用!1000M内存50G数据盘的MySQL可免费体验30天,点击左下角“阅读原文”立即领取~

↓↓点“阅读原文”免费试用

好文和朋友一起看!

var first_sceen__time = (+new Date());if ("" == 1 && document.getElementById('js_content')) { document.getElementById('js_content').addEventListener("selectstart",function(e){ e.preventDefault(); }); } (function(){ if (navigator.userAgent.indexOf("WindowsWechat") != -1){ var link = document.createElement('link'); var head = document.getElementsByTagName('head')[0]; link.rel = 'stylesheet'; link.type = 'text/css'; link.href = "//res.wx.qq.com/mmbizwap/zh_CN/htmledition/style/page/appmsg_new/winwx45ba31.css"; head.appendChild(link); } })();

鲁越

赞赏

长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

阅读原文

阅读

分享 在看

已同步到看一看

取消 发送

我知道了

朋友会在“发现-看一看”看到你“在看”的内容

确定

已同步到看一看写下你的想法

最多200字,当前共字 发送

已发送

朋友将在看一看看到

确定

写下你的想法...

取消

发布到看一看

确定

最多200字,当前共字

发送中

微信扫一扫 关注该公众号

微信扫一扫 使用小程序

即将打开""小程序

取消 打开

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯云数据库 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 朋友会在“发现-看一看”看到你“在看”的内容
  • 朋友将在看一看看到
  • 发布到看一看
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档