<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[刘新修]]></title> 
<link>http://pic1.liuxinxiu.com:80/index.php</link> 
<description><![CDATA[刘新修的个人博客 (Liuxinxiu'S Blog)]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[刘新修]]></copyright>
<item>
<link>http://pic1.liuxinxiu.com:80/Mysql_max_allowed_packet/</link>
<title><![CDATA[MySQL server has gone away 问题的解决方法]]></title> 
<author>刘新修 &lt;admin@yourname.com&gt;</author>
<category><![CDATA[数据库技术]]></category>
<pubDate>Thu, 02 Mar 2017 02:26:13 +0000</pubDate> 
<guid>http://pic1.liuxinxiu.com:80/Mysql_max_allowed_packet/</guid> 
<description>
<![CDATA[ 
	<p><strong><span style="color: rgb(255, 0, 0);">&nbsp;<span style="font-family: tahoma, arial, 宋体;">mysql出现ERROR : (2006, 'MySQL server has gone away') 的问题意思就是指client和MySQL server之间的链接断开了。</span></span></strong></p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">造成这样的原因一般是sql操作的时间过长，或者是传送的数据太大(例如使用insert ... values的语句过长， 这种情况可以通过修改max_allowed_packed的配置参数来避免，也可以在程序中将数据分批插入)。</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">产生这个问题的原因有很多，总结下网上的分析：</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;"><strong>原因一. MySQL 服务宕了</strong></p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">判断是否属于这个原因的方法很简单，进入mysql控制台，查看mysql的运行时长</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">mysql&gt; show global status like 'uptime';<br />+---------------+---------+<br />&#124; Variable_name &#124; Value&nbsp;&nbsp; &#124;<br />+---------------+---------+<br />&#124; Uptime&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; 3414707 &#124;<br />+---------------+---------+</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">1 row in set或者查看MySQL的报错日志，看看有没有重启的信息</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">如果uptime数值很大，表明mysql服务运行了很久了。说明最近服务没有重启过。<br />如果日志没有相关信息，也表名mysql服务最近没有重启过，可以继续检查下面几项内容。</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;"><strong>原因二. mysql连接超时</strong></p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">即某个mysql长连接很久没有新的请求发起，达到了server端的timeout，被server强行关闭。<br />此后再通过这个connection发起查询的时候，就会报错server has gone away<br />（大部分PHP脚本就是属于此类）</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">mysql&gt; show global variables like '%timeout';<br />+----------------------------+----------+<br />&#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; Value&nbsp;&nbsp;&nbsp; &#124;<br />+----------------------------+----------+<br />&#124; connect_timeout&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; 10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br />&#124; delayed_insert_timeout&nbsp;&nbsp;&nbsp;&nbsp; &#124; 300&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br />&#124; innodb_lock_wait_timeout&nbsp;&nbsp; &#124; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br />&#124; innodb_rollback_on_timeout &#124; OFF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br />&#124; interactive_timeout&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; 28800&nbsp;&nbsp;&nbsp; &#124;<br />&#124; lock_wait_timeout&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; 31536000 &#124;<br />&#124; net_read_timeout&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; 30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br />&#124; net_write_timeout&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; 60&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br />&#124; slave_net_timeout&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; 3600&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br />&#124; wait_timeout&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; 28800&nbsp;&nbsp;&nbsp; &#124;<br />+----------------------------+----------+<br />10 rows in set</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">wait_timeout 是28800秒，即mysql链接在无操作28800秒后被自动关闭</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;"><strong>原因三. mysql请求链接进程被主动kill</strong></p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">这种情况和原因二相似，只是一个是人为一个是MYSQL自己的动作</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">mysql&gt; show global status like 'com_kill';<br />+---------------+-------+<br />&#124; Variable_name &#124; Value &#124;<br />+---------------+-------+<br />&#124; Com_kill&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; 21&nbsp;&nbsp;&nbsp; &#124;<br />+---------------+-------+<br />1 row in set原因四. Your SQL statement was too large.</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">当查询的结果集超过 max_allowed_packet 也会出现这样的报错。定位方法是打出相关报错的语句。</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">用select * into outfile 的方式导出到文件，查看文件大小是否超过 max_allowed_packet ，如果超过则需要调整参数，或者优化语句。</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">mysql&gt; show global variables like 'max_allowed_packet';<br />+--------------------+---------+<br />&#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; Value&nbsp;&nbsp; &#124;<br />+--------------------+---------+<br />&#124; max_allowed_packet &#124; 1048576 &#124;<br />+--------------------+---------+<br />1 row in set (0.00 sec)<br /><br />修改参数：</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;">mysql&gt; set global max_allowed_packet=1024*1024*16;<br />mysql&gt; show global variables like 'max_allowed_packet';<br />+--------------------+----------+<br />&#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124; Value&nbsp;&nbsp;&nbsp; &#124;<br />+--------------------+----------+<br />&#124; max_allowed_packet &#124; 16777216 &#124;<br />+--------------------+----------+<br />1 row in set (0.00 sec)<br /><br /><strong>以下是补充：<br /></strong><br />应用程序（比如PHP）长时间的执行批量的MYSQL语句。执行一个SQL，但SQL语句过大或者语句中含有BLOB或者longblob字段。比如，图片数据的处理。都容易引起MySQL server has gone away。&nbsp;<br /><br />今天遇到类似的情景，MySQL只是冷冷的说：MySQL server has gone away。&nbsp;<br /><br />大概浏览了一下，主要可能是因为以下几种原因：&nbsp;<br />一种可能是发送的SQL语句太长，以致超过了max_allowed_packet的大小，如果是这种原因，你只要修改my.cnf，加大max_allowed_packet的值即可。&nbsp;</p><p style="margin-bottom: 0px; padding-top: 5px; padding-bottom: 5px; font-family: tahoma, arial, 宋体;"><a href="http://at.liuxinxiu.com/2017/03/image/Mysql_my_cnf_max_allowed_packet.jpg" target="_blank"><img src="http://at.liuxinxiu.com/2017/03/image/Mysql_my_cnf_max_allowed_packet.jpg" width="615" height="698" alt="" /></a><br /><br />还有一种可能是因为某些原因导致超时，比如说程序中获取数据库连接时采用了Singleton的做法，虽然多次连接数据库，但其实使用的都是同一个连接，而且程序中某两次操作数据库的间隔时间超过了wait_timeout（SHOW STATUS能看到此设置），那么就可能出现问题。最简单的处理方式就是把wait_timeout改大，当然你也可以在程序里时不时顺手mysql_ping()一下，这样MySQL就知道它不是一个人在战斗。&nbsp;<br /><br /><strong>解决MySQL server has gone away</strong>&nbsp;<br /><br />1、应用程序（比如PHP）长时间的执行批量的MYSQL语句。最常见的就是采集或者新旧数据转化。&nbsp;<br />解决方案：&nbsp;<br />在my.cnf文件中添加或者修改以下两个变量：&nbsp;<br />wait_timeout=2880000&nbsp;<br />interactive_timeout = 2880000&nbsp;<br />关于两个变量的具体说明可以google或者看官方手册。如果不能修改my.cnf，则可以在连接数据库的时候设置CLIENT_INTERACTIVE，比如：&nbsp;<br />sql = &quot;set interactive_timeout=24*3600&quot;;&nbsp;<br />mysql_real_query(...)&nbsp;<br /><br /><br />2、执行一个SQL，但SQL语句过大或者语句中含有BLOB或者longblob字段。比如，图片数据的处理&nbsp;<br />解决方案：&nbsp;<br />在my.cnf文件中添加或者修改以下变量：&nbsp;<br />max_allowed_packet = 10M(也可以设置自己需要的大小)&nbsp;<br />max_allowed_packet 参数的作用是，用来控制其通信缓冲区的最大长度。&nbsp;<br /><br /><br />最近做网站有一个站要用到WEB网页采集器功能，当一个PHP脚本在请求URL的时候，可能这个被请求的网页非常慢慢，超过了mysql的 wait-timeout时间，然后当网页内容被抓回来后，准备插入到MySQL的时候，发现MySQL的连接超时关闭了，于是就出现了&ldquo;MySQL server has gone away&rdquo;这样的错误提示，解决这个问题，我的经验有以下两点，或许对大家有用处：&nbsp;<br /><strong>第 一种方法：&nbsp;<br /></strong>当然是增加你的 wait-timeout值，这个参数是在my.cnf(在Windows下台下面是my.ini）中设置，我的数据库负荷稍微大一点，所以，我设置的值 为10，（这个值的单位是秒，意思是当一个数据库连接在10秒钟内没有任何操作的话，就会强行关闭，我使用的不是永久链接 （mysql_pconnect),用的是mysql_connect,关于这个wait-timeout的效果你可以在MySQL的进程列表中看到 （show processlist) ），你可以把这个wait-timeout设置成更大，比如300秒，呵呵，一般来讲300秒足够用了，其实你也可以不用设置，MySQL默认是8个小 时。情况由你的服务器和站点来定。&nbsp;<br /><strong>第二种方法：</strong>&nbsp;<br />这也是我个人认为最好的方法，即检查 MySQL的链接状态，使其重新链接。&nbsp;<br />可能大家都知道有mysql_ping这么一个函数，在很多资料中都说这个mysql_ping的 API会检查数据库是否链接，如果是断开的话会尝试重新连接，但在我的测试过程中发现事实并不是这样子的，是有条件的，必须要通过 mysql_options这个C API传递相关参数，让MYSQL有断开自动链接的选项（MySQL默认为不自动连接），但我测试中发现PHP的MySQL的API中并不带这个函数，你重新编辑MySQL吧，呵呵。但mysql_ping这个函数还是终于能用得上的，只是要在其中有一个小小的操作技巧：&nbsp;<br />这是我的的数据库操 作类中间的一个函数&nbsp;</p>
]]>
</description>
</item><item>
<link>http://pic1.liuxinxiu.com:80/Mysql_max_allowed_packet/#blogcomment</link>
<title><![CDATA[[评论] MySQL server has gone away 问题的解决方法]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://pic1.liuxinxiu.com:80/Mysql_max_allowed_packet/#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>