标题:[实践OK]Mysql客户端连接和PHP连接时interactive_timeout和wait_timeout的一个关系,以及在Mysql做一些超长的处理时mysql gone away的原因。 出处:向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除 时间:Tue, 14 Nov 2017 16:17:20 +0000 作者:jackxiang 地址:http://jackxiang.com/post/9518/ 内容: 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连接结果都一样: query('set names utf8;'); //你可能会用到的utf-8,哈哈 $rs = $db->query("show variables like 'interactive_timeout'"); $result_arr = $rs->fetchAll(); print_r($result_arr); $rs = $db->query("show variables like 'wait_timeout'"); $result_arr = $rs->fetchAll(); print_r($result_arr); echo "show global variables like '%wait_timeout%'\n\n"; $rs = $db->query("show global variables like 'interactive_timeout'"); $result_arr = $rs->fetchAll(); print_r($result_arr); $rs = $db->query("show global variables like 'wait_timeout'"); $result_arr = $rs->fetchAll(); print_r($result_arr); Mysqlli: $mysqli = new mysqli("localhost", "root", "******", "mysql"); $query="show variables like '%timeout%'"; $result=$mysqli->query($query); if ($result) { if($result->num_rows>0){ while($row =$result->fetch_array() ){ print_r($row); } } }else { echo "查询失败"; } $result->free(); $mysqli->close(); die; php /tmp/mysql.php 说明其PHP客户端并没有像mysql的命令行一样修改客户端的,而值都为配置的值: | interactive_timeout | 28800 | | wait_timeout | 10 | PHP7不支持Mysql的mysql_connect驱动啦: exec('set session wait_timeout=10000'); 但这样一来,可能会导致更多的mysql睡眠连接。 Generated by Jackxiang's Bo-blog 2.1.1 Release