PHP中MySQL server has gone away问题

一.背景

之前在Codeigniter里面写过类似console命令行的脚本. 脚本里存在sleep语句时间比较久, 导致出现一个现象就是sleep之前的SQL都是操作成功的,但是sleep之后,再执行SQL操作竟然报错: MySQL server has gone away. 也就是mysql的这个连接失效. 后来分析才知道, MySQL中存在2个重要的配置参数:

interactive_timeout
wait_timeout

这2个参数的单位都是秒(s). 默认是8小时(28800). interactive_timeout从单词上看指的是交互超时时间. mysql的连接方式一般分为2种, 一种称之为"交互式", 一种称为"非交互式". 一般常见的使用mysql -u root xxx之类的或者主从复制的连接为"交互式连接", 使用如Java的JDBC、PHP的PDO驱动连接的方式一般是"非交互式连接". 然而interactive_timeout如果未修改的情况下,这个值是一直不会变的,但是wait_timeout在不同连接方式下,值是不一样的.

wait_timeout在"交互式连接"下, 其值是interactive_timeout的值. 如果在"非交互式连接"情况下, 则wait_timeout的值是原来mysql.cnf中配置的原始值.

最终起作用的只是wait_timeout的值.这配置项限定了处于sleep状态(通过 show processlist查看当前连接数情况)的连接,如果这个连接sleep休眠时间超过wait_timeout的值,则这个连接被断掉或者说被清理掉.

二.wait_timeout分析

1.首先查看mysql.conf配置

解决MySQL server has gone away错误的方案

首先我们配置了interactive_timeout=10 wait_timeout=5, 此时通过mysql客户端(交互式连接)查看这2个配置项的值: show variables like ‘%timeout%';

2.交互式连接

解决MySQL server has gone away错误的方案

客户端的结果: wait_timeout竟然不是我们msyql.conf配置的10s, 而是 5s.

那我们再来看看PHP连接MySQL(非交互式连接),执行相同的语句,得到什么结构:

3.非交互式连接

解决MySQL server has gone away错误的方案

解决MySQL server has gone away错误的方案

此时wait_timeout是我们原来在mysql.cnf配置的值了.

综上所述: wait_timeout这个值,在不同的"连接模式"下面,拿到的值是不一样的.

三.gone away原因分析

结合上面的情况,我们就知道了。 一开始某些SQL执行成功,但是后面的SQL执行失败报错gone away,大部分原因就是这个连接被闲置超过了wait_timeout,mysql服务器单方面断掉了这个连接。但是客户端代码,还是在用这个连接变量,以为连接还是ok的(其实mysql server端已经断开了,只是我们以为这个连接还有效),去执行SQL必然报错.

那么我们怎么解决这个情况呢"htmlcode">

$db = db();

try {
   fun1$db); // 一开始执行成功
   sleep(3600*10) // 假设sleep了10个小时
   fun2($db);   // 10小时之后 由于连接已经被mysql干掉 导致报错 gone away
}catch(Exception $e) {
  // 报错后 我们把无效的连接close 在 open新的连接 
  $db->close();
  $db->open();
  // 再拿到新的连接执行
  // fun2($db)  
}

3.如果是使用类似swoole或者easyswoole框架, 建议使用mysql pool连接池的形式.并且一般连接池都有关于心跳检查ping、连接存活检测间隔时间设置、最大闲置连接数等等设置, 只要配置一次就好了。 例如可以配置测活连接间隔时间短一点,来保证连接不会被msyql服务器干掉.例如 easyswoole配置:

解决MySQL server has gone away错误的方案

例如之前我设置wait_timeout=10, 但是如果我没修改这个easyswoole的mysql连接池测活间隔时间变小, 同样会出现gone way的情况. 第一次访问接口成功返回SQL执行结果,但是超过10s以后我再次访问接口,报错mysql has gone away。修改setIntervalCheckTime()之后,就不会出现这个问题了. 我们通过mysql的show processlist;查看连接数情况:

解决MySQL server has gone away错误的方案

这些都是easyswoole帮我们维护的连接数. 当sleep超过3秒时, 由于检查时间是3秒存活, 连接池帮我们保活检查, sleep的时间又从0开始计算.

下面是其他网友的补充

进入MySQL

cmd

mysql -u用户名 -p密码

在我们使用mysql导入大文件sql时可能会报MySQL server has gone away错误,该问题是max_allowed_packet配置的默认值设置太小,只需要相应调大该项的值之后再次导入便能成功。该项的作用是限制mysql服务端接收到的包的大小,因此如果导入的文件过大则可能会超过该项设置的值从而导致导入不成功!下面我们来看一下如何查看以及设置该项的值。

查看 max_allowed_packet 的值

show global variables like 'max_allowed_packet';
+--------------------+---------+
| Variable_name | Value |
+--------------------+---------+
| max_allowed_packet | 4194304 |
+--------------------+---------+

可以看到默认情况下该项的大小只有4M,接下来将该值设置成150M(1024*1024*150)

set global max_allowed_packet=157286400;

此时再查看大小

show global variables like 'max_allowed_packet';

解决MySQL server has gone away错误的方案

通过调大该值,一般来说再次导入数据量大的sql应该就能成功了,如果任然报错,则继续再调大一些就行,请注意通过在命令行中进行设置只对当前有效,重启mysql服务之后则恢复默认值,但可以通过修改配置文件(可以在配置文件my.cnf中添加max_allowed_packet=150M即可)来达到永久有效的目的,可其实我们并不是经常有这种大量数据的导入操作,所以个人觉得通过命令行使得当前配置生效即可,没有必要修改配置文件。

以上就是本次介绍的全部相关知识点内容,希望整理的内容能够帮助到你。

广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。