结论

mysqli没有处理对端(MySQL server)的断开请求。在send时,收到对端(MySQL server)的RST,会打印MySQL server has gone away。

环境

xxxx@xxxx:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 8.4 (jessie)
Release: 8.4
Codename: jessie
xxxx@xxxx:~$ php --version
PHP 5.6.30 (cli) (built: Oct 27 2017 11:18:47) (DEBUG)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies

MySQL server的官方解释

https://dev.mysql.com/doc/refman/5.7/en/gone-away.html

官方文档非常罗嗦,简单说来就是:

  • 无效链接

    1.关闭连接后仍然发起查询如超时断开、主动断开

    2.fork子进程使用父进程的链接)。
  • 查询太大。
  • 无访问权限。
  • 网络问题(防火墙等)。

都可能造成MySQL server has gone away。

而我遇到的问题属于无效链接。

抓包分析



可以看到。

No.469 是 MySQL server的tcp断开请求,apache的工作进程并没有返回FIN。

netstat的结果也证明了这一点:

tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      11439/mysqld
tcp 1 0 127.0.0.1:56236 127.0.0.1:3306 CLOSE_WAIT 21523/apache2
tcp 1 0 127.0.0.1:56196 127.0.0.1:3306 CLOSE_WAIT 21466/apache2
tcp 1 0 127.0.0.1:56191 127.0.0.1:3306 CLOSE_WAIT 21523/apache2
tcp 0 0 127.0.0.1:3306 127.0.0.1:56247 FIN_WAIT2 -
tcp 0 0 127.0.0.1:3306 127.0.0.1:56236 FIN_WAIT2 -
tcp 1 0 127.0.0.1:56247 127.0.0.1:3306 CLOSE_WAIT 21466/apache2

No.2113 是 MySQL client 的 Change User 请求,值得注意的是,仍然用原端口(链接)和MySQL server通信。被MySQL server RST,触发MySQL server has gone away

开始我认为这是一个BUG,于是开始从源码中寻找答案。

源码分析

在脚本层定位到链接、报错发生在:

$this->_mysqli->real_connect

对应的c函数:

mysqli_noapi.c:mysqli_common_connect

因为链接由apache工作进程持有,mysqli拓展作为动态库载入,若apache需要对MySQL server的FIN包做出处理,mysqli 拓展必须在建立链接时,将链接ID传给apache。

但我没找到这样的逻辑。

结论是:

实现就是如此。MySQL断开链接时,mysqli对失效链接无任何处理。

mysqli在send时才能发现链接失效,若链接失败,会重连一次。

调试证实

No.2113 被RST

mysqlnd_auth.c:226,单步执行后,tcpdump抓到

15:21:20.300274 IP localhost.i.nease.net.56230 > localhost.i.nease.net.mysql: Flags [P.], seq 2540548209:2540548279, ack 3116587272, win 86, options [nop,nop,TS val 888121188 ecr 888020891], length 70
15:21:20.300305 IP localhost.i.nease.net.mysql > localhost.i.nease.net.56230: Flags [R], seq 3116587272, win 0, length 0

错误信息来源:

mysqlnd_auth.c:234

(gdb) n
234 COPY_CLIENT_ERROR(*conn->error_info, chg_user_resp->error_info); (gdb) p conn->error_info.error
$14 = "MySQL server has gone away", '\000' <repeats 486 times>

mysqli使用失效链接时,被MySQL server RST。

重连

mysqli_nonapi.c

244             if (mysqlnd_connect(mysql->mysql, hostname, username, passwd, passwd_len, dbname, dbname_len,
(gdb) n

tcpdump 结果

15:27:33.105716 IP localhost.i.nease.net.56247 > localhost.i.nease.net.mysql: Flags [S], seq 842214159, win 43690, options [mss 65495,sackOK,TS val 888214389 ecr 0,nop,wscale 9], length 0
15:27:33.105738 IP localhost.i.nease.net.mysql > localhost.i.nease.net.56247: Flags [S.], seq 3337503184, ack 842214160, win 43690, options [mss 65495,sackOK,TS val 888214389 ecr 888214389,nop,wscale 9], length 0
15:27:33.105771 IP localhost.i.nease.net.56247 > localhost.i.nease.net.mysql: Flags [.], ack 1, win 86, options [nop,nop,TS val 888214389 ecr 888214389], length 0
15:27:33.106227 IP localhost.i.nease.net.mysql > localhost.i.nease.net.56247: Flags [P.], seq 1:79, ack 1, win 86, options [nop,nop,TS val 888214389 ecr 888214389], length 78
15:27:33.106241 IP localhost.i.nease.net.56247 > localhost.i.nease.net.mysql: Flags [.], ack 79, win 86, options [nop,nop,TS val 888214389 ecr 888214389], length 0
15:27:33.106362 IP localhost.i.nease.net.56247 > localhost.i.nease.net.mysql: Flags [P.], seq 1:122, ack 79, win 86, options [nop,nop,TS val 888214389 ecr 888214389], length 121
15:27:33.106373 IP localhost.i.nease.net.mysql > localhost.i.nease.net.56247: Flags [.], ack 122, win 86, options [nop,nop,TS val 888214389 ecr 888214389], length 0
15:27:33.106479 IP localhost.i.nease.net.mysql > localhost.i.nease.net.56247: Flags [P.], seq 79:90, ack 122, win 86, options [nop,nop,TS val 888214389 ecr 888214389], length 11
15:27:33.142634 IP localhost.i.nease.net.56247 > localhost.i.nease.net.mysql: Flags [.], ack 90, win 86, options [nop,nop,TS val 888214399 ecr 888214389], length 0

可以看到。因mysqli_common_connect在链接失效时,会重试一次。

项目使用了pconnect,大量长链接因空闲超时被断开,下次请求时,链接失效会导致gone away,因为有重连。该报错可忽略。

php mysqli MySQL server has gone away 问题分析的更多相关文章

  1. Python pandas ERROR 2006 (HY000): MySQL server has gone away

    之前在做python pandas大数据分析的时候,在将分析后的数据存入mysql的时候报ERROR 2006 (HY000): MySQL server has gone away 原因分析:在对百 ...

  2. gearman中worker常驻后台,导致MySQL server has gone away

    产生这个原因主要有如下几点: 1.mysql服务宕机了 2.长时间没有操作,超过了wait_timeout的设置,mysql自动断开 3.mysql请求链接被主动kill 4.发送的请求或返回结果过大 ...

  3. phpMyAdmin出现找不到mysql扩展和Cannot log in to the MySQL server问题

    环境:Centos6.5,Apache2.4, PHP5.5, MySql5.6. phpMyAdmin版本:https://files.phpmyadmin.net/phpMyAdmin/4.4.1 ...

  4. 2003-Can't connect to mysql server on localhost (10061)

    mysql数据库出现2003-Can't connect to mysql server on localhost (10061)问题 解决办法:查看wampserver服务器是否启动,如果没有启动启 ...

  5. ERROR 2003 (HY000): Can't connect to MySQL server on 'ip address' (111)的处理办法

    远程连接mysql数据库时可以使用以下指令 mysql -h 192.168.1.104 -u root -p 如果是初次安装mysql,需要将所有/etc/mysql/内的所有配置文件的bind-a ...

  6. mySql 远程连接(is not allowed to connect to this MySQL server)

    如果你想连接你的mysql的时候发生这个错误: ERROR 1130: Host '192.168.1.3' is not allowed to connect to this MySQL serve ...

  7. 报错:1130-host ... is not allowed to connect to this MySql server

    报错:1130-host ... is not allowed to connect to this MySql server   解决方法: 1. 改表法. 可能是你的帐号不允许从远程登陆,只能在l ...

  8. 连接Mysql提示Can’t connect to local MySQL server through socket的解决方法

    mysql,mysqldump,Mysqladmin,php连接mysql服务常会提示下面错误: ERROR 2002 (HY000): Can't connect to local MySQL se ...

  9. ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

    有时候,当我们使用"mysql"."mysqladmin"."mysqldump"等命令管理数据库时,服务器抛出类似如下错误: 一.错误现场 ...

随机推荐

  1. openfire:Openfire源代码在eclipse中的运行配置 + 与spark结合进行二次开发

    1.下载源代码:http://www.igniterealtime.org/downloads/source.jsp 2.把源代码解压出的openfire_src文件夹放至eclipse workpl ...

  2. LINUX - awk命令之NF和$NF区别 (转)

    NF和$NF 区别问答:(转)1.awk中$NF是什么意思?#pwd/usr/local/etc~# echo $PWD | awk -F/ '{print $NF}'etcNF代表:浏览记录的域的个 ...

  3. java.lang.NoClassDefFoundError: com/mchange/v2/ser/Indirector

    在使用C3P0连接池的时候,发现了这个错误-.原来要使用C3P0的使用,不仅仅要导入c3p0-0.9.2-pre1.jar这个jar包,还要导入mchange-commons-0.2.jar这个jar ...

  4. layer子层给父层页面元素赋值,以达到向父层页面传值的效果

    父层: jsp中: //页面上添加一个隐藏的输入框待用于被子层设置value,从而将子层的数据传递到此页面 <input type="hidden" id="get ...

  5. NameError: name 'messagebox' is not defined 错误处理

    写了段代码,想在按下button的时候跳个提示框出来,调试的时候提示了messagebox未定义 from tkinter import * def test_show(): messagebox.s ...

  6. Codeforce E. Fire

    E. Fire time limit per test 2 seconds memory limit per test 256 megabytes input standard input outpu ...

  7. oss滤网图片音视频过滤(1)内容检测

    图片音视频过滤有好多方法,我这里就不一一介绍了,这篇文章只是简单介绍一下我在项目中使用阿里云oss滤网过滤的步骤 1.所遇问题: 1.图片视频鉴别时要设置textScanRequest.setUriP ...

  8. ARKit 增强现实平台 尝试(Xcode9 iOS11 A9处理器)

    一, Xcode 将加​​载其主页面并显示模板选择页面.模板简化了入门过程.然后选择增强现实应用程序图标,单击"下一步"按钮. 二, 运行程序会看到一个飞机 三,尝试更换模型 在这 ...

  9. ThinkPHP控制器输出防止乱码小技巧

    在控制器中加一句:试试看 header('content-type:text/html;charset=utf-8');

  10. 替换应用程序DLL动态库的详细方法步骤 (gts.dll为例)

    在C++ builder编译器IDE软件下 1.View -Project Manageer --找到需要替换的x.dll(gts.dll)对应的x.lib(gts.lib),然后Remove2.Pr ...