[实践OK]Mysql客户端连接和PHP连接时interactive_timeout和wait_timeout的一个关系,以及在Mysql做一些超长的处理时mysql gone away的原因。

jackxiang 2017-11-14 16:17 | |
interactive_timeout :连接空闲超时时间。与服务器端无交互状态的连接,直到被服务器端强制关闭而等待的时间。
    interactive_timeout和wait_timeout意义虽然相同,但是有使用对象有本质的区别。interactive_timeout针对交互式连接(比如通过mysql客户端连接数据库),wait_timeout针对非交互式连接(比如一般在PHP中使用PDO连接数据库,当然你可以设置CLIENT_INTERACTIVE选项来改变)。所谓的交互式连接,即在mysql_real_connect()函数中使用了CLIENT_INTERACTIVE选项。
wait_timeout:连接空闲超时时间。与服务器端无交互状态的连接,直到被服务器端强制关闭而等待的时间。可以认为是服务器端连接空闲的时间,空闲超过这个时间将自动关闭。

交互连接:
interactive_timeout 需在mysql_connect()设置CLIENT_INTERACTIVE选项后起作用,并被赋值为wait_timeout;  #Mysql自己的客户端mysql命令。
mysql>set global wait_timeout = 60; 对当前交互链接有效; (由于mysql的BUG所有这边必须加global)
mysql>set global interactive_timeout = 60; 对后续起的交互链接有效;


解决MySQL server has gone away
应用程序(比如PHP)长时间的执行批量的MYSQL语句。最常见的就是采集或者新旧数据转化。
解决方案:
在my.cnf文件中添加或者修改以下两个变量:
wait_timeout=2880000
interactive_timeout = 2880000
关于两个变量的具体说明可以google或者看官方手册。如果不能修改my.cnf,则可以在连接数据库的时候设置CLIENT_INTERACTIVE,比如:
sql = "set interactive_timeout=24*3600";
mysql_real_query(...)

wait_timeout过大有弊端,其体现就是MySQL里大量的SLEEP进程无法及时释放,拖累系统性能,不过也不能把这个指设置的过小,否则你可能会遭遇到“MySQL has gone away”之类的问题,通常来说,我觉得把wait_timeout设置为10是个不错的选择,但某些情况下可能也会出问题,比如说有一个CRON脚本,其中两次SQL查询的间隔时间大于10秒的话,那么这个设置就有问题了(当然,这也不是不能解决的问题,你可以在程序里时不时mysql_ping一下,以便服务器知道你还活着,重新计算wait_timeout时间)

本质:
变量wait_timeout:服务器关闭非交互连接之前等待活动的秒数。也就是说你PHP获取一次数据后作计算了,并没有释放Mysql连接句柄,而你处理完后,继续获取数据,这个中间等待的秒数。  为了防止出现这个问题,用了mysql_ping:https://mo2g.com/view/128/
问题:这个秒数,DBA一般写10秒,能否突破和Mysql的Client一样,让它的值和interactive_timeout一样呢?

From:http://www.04007.cn/article/292.html
============================================================================================
总之,Mysql的原生客户端,在设置其wait_timeout的值时不受全局的设置限制,均等于全局(/etc/my.cnf)interactive_timeout的值,而PHP则并不改变全局的值,而是里面配置wait_timeout多少,此次连接就是多少,当然,也提供了类似Mysql自带客户端的参数。

my.cnf:
interactive_timeout = 28800
wait_timeout = 28800

mysql> show variables like '%timeout%';
| interactive_timeout         | 28800    |
| wait_timeout                | 28800    |

修改一下重新启动Mysql后,直接用Mysql客户端连接?如下:
interactive_timeout = 29800
wait_timeout = 28800

mysql
mysql> show variables like '%timeout%';

| wait_timeout                | 29800    |
| interactive_timeout         | 29800    |

而Show全局变量呢,还是显示my.cnf里设置的,但这儿会被个性的mysql在连接时作了设置而覆盖:
mysql> show global variables like "%timeout%";        
| interactive_timeout         | 29800    |
| wait_timeout                | 28800    |

PDO连接和Mysqlli连接结果都一样:


Mysqlli:

php /tmp/mysql.php

说明其PHP客户端并没有像mysql的命令行一样修改客户端的,而值都为配置的值:
| interactive_timeout         | 28800    |
| wait_timeout                | 10       |

PHP7不支持Mysql的mysql_connect驱动啦:

Call to undefined function mysql_connect() in /tmp/mysql.php:6
Stack trace:
#0 {main}
  thrown in /tmp/mysql.php on line 6

Call to undefined function mysql_real_connect() in /tmp/mysql.php:6
Stack trace:
#0 {main}
  thrown in /tmp/mysql.php on line 6
================================================================================
mysql_connect/mysql_real_connect()中使用CLIENT_INTERACTIVE选项的客户端。现在PHP7已经废弃上面这两个Mysql的连接函数了。
新的PDO直接用设置了,更灵活:
mysql server 的配置wait_timeout如果过小,就会导致PDO出现mysql has gone away错误。
解决办法,设置较长的会话超时时间。
$pdo->exec('set session wait_timeout=10000');
但这样一来,可能会导致更多的mysql睡眠连接。

作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:http://jackxiang.com/post/9518/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!


最后编辑: jackxiang 编辑于2017-11-14 17:17
评论列表
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]