MySQL server has gone away 问题的解决方法

mysql 出现 ERROR : (2006, ‘MySQL server has gone away’) 的问题意思就是指 client 和 MySQL server 之间的链接断开了。   造成这样的原因一般是 sql 操作的时间过长,或者是传送的数据太大 (例如使用 insert … values 的语句过长, 这种情况可以通过修改 max_allowed_packed 的配置参数来避免,也可以在程序中将数据分批插入)。 产生这个问题的原因有很多,总结下网上的分析:

原因一. MySQL 服务宕了

  判断是否属于这个原因的方法很简单,进入 mysql 控制台,查看 mysql 的运行时长 mysql> show global status like ‘uptime’; +—————+———+ | Variable_name | Value | +—————+———+ | Uptime | 3414707 | +—————+———+ 1 row in set 或者查看 MySQL 的报错日志,看看有没有重启的信息;如果 uptime 数值很大,表明 mysql 服务运行了很久了。说明最近服务没有重启过。如果日志没有相关信息,也表名 mysql 服务最近没有重启过,可以继续检查下面几项内容。

原因二. mysql 连接超时

即某个 mysql 长连接很久没有新的请求发起,达到了 server 端的 timeout,被 server 强行关闭。 此后再通过这个 connection 发起查询的时候,就会报错 server has gone away (大部分 PHP 脚本就是属于此类) mysql> show global variables like ‘%timeout’; +—————————-+———-+ | Variable_name | Value | +—————————-+———-+ | connect_timeout | 10 | | delayed_insert_timeout | 300 | | innodb_lock_wait_timeout | 50 | | innodb_rollback_on_timeout | OFF | | interactive_timeout | 28800 | | lock_wait_timeout | 31536000 | | net_read_timeout | 30 | | net_write_timeout | 60 | | slave_net_timeout | 3600 | | wait_timeout | 28800 | +—————————-+———-+ 10 rows in set wait_timeout 是 28800 秒,即 mysql 链接在无操作 28800 秒后被自动关闭

原因三. mysql 请求链接进程被主动 kill

这种情况和原因二相似,只是一个是人为一个是 MYSQL 自己的动作 mysql> show global status like ‘com_kill’; +—————+——-+ | Variable_name | Value | +—————+——-+ | Com_kill | 21 | +—————+——-+ 1 row in set 原因四. Your SQL statement was too large.   当查询的结果集超过 max_allowed_packet 也会出现这样的报错。定位方法是打出相关报错的语句。用 select * into outfile 的方式导出到文件,查看文件大小是否超过 max_allowed_packet ,如果超过则需要调整参数,或者优化语句。 mysql> show global variables like ‘max_allowed_packet’; +——————–+———+ | Variable_name | Value | +——————–+———+ | max_allowed_packet | 1048576 | +——————–+———+ 1 row in set (0.00 sec) 修改参数: mysql> set global max_allowed_packet=1024102416; mysql> show global variables like ‘max_allowed_packet’; +——————–+———-+ | Variable_name | Value | +——————–+———-+ | max_allowed_packet | 16777216 | +——————–+———-+ 1 row in set (0.00 sec)

应用程序长时间的执行批量的 MYSQL 语句。执行一个 SQL,但 SQL 语句过大或者语句中含有 BLOB 或者 longblob 字段。比如,图片数据的处理。都容易引起 MySQL server has gone away。   今天遇到类似的情景,MySQL 只是冷冷的说:MySQL server has gone away。   大概浏览了一下,主要可能是因为以下几种原因:   一种可能是发送的 SQL 语句太长,以致超过了 max_allowed_packet 的大小,如果是这种原因,你只要修改 my.cnf,加大 max_allowed_packet 的值即可。   还有一种可能是因为某些原因导致超时,比如说程序中获取数据库连接时采用了 Singleton 的做法,虽然多次连接数据库,但其实使用的都是同一个连接,而且程序中某两次操作数据库的间隔时间超过了 wait_timeout(SHOW STATUS 能看到此设置),那么就可能出现问题。最简单的处理方式就是把 wait_timeout 改大,当然你也可以在程序里时不时顺手 mysql_ping()一下,这样 MySQL 就知道它不是一个人在战斗。   解决 MySQL server has gone away   1、应用程序长时间的执行批量的 MYSQL 语句。最常见的就是采集或者新旧数据转化。   解决方案:   在 my.cnf 文件中添加或者修改以下两个变量: wait_timeout=2880000 interactive_timeout = 2880000  关于两个变量的具体说明可以 google 或者看官方手册。如果不能修改 my.cnf,则可以在连接数据库的时候设置 CLIENT_INTERACTIVE,比如: sql = “set interactive_timeout=24*3600”; mysql_real_query(…)   2、执行一个 SQL,但 SQL 语句过大或者语句中含有 BLOB 或者 longblob 字段。比如,图片数据的处理   解决方案:   在 my.cnf 文件中添加或者修改以下变量:

max_allowed_packet = 10M(也可以设置自己需要的大小) ,max_allowed_packet 参数的作用是,用来控制其通信缓冲区的最大长度。

一、(2006, ‘MySQL server has gone away’)
错误原因

          从字面理解,就是你连接的 MySQL 已经走人了,不在了。相当于你和另外一个人打电话,你一直没有挂电话,但是你把电话放一边了,直到你重新拎起电话想说点啥,才听到里面『嘟,嘟,嘟,嘟…』的挂机声,于是你就知道电话另一头的人已经 gone away 了。

线上碰到这个问题时,通常就是抛一个异常,然后(主动 / 被动)重新连接一下,你下次就重新执行一下要执行的语句就行。这就像你觉得有一番话非说不可,然后重新拨了个电话过去。

什么情况下会 gone away?就像刚才说的,当你拿着一个电话太久,又不说话的时候,对面肯定就把你挂了;当 sqlalchemy 与 MySQL 建立了一个连接,而 sqlalchemy 又不对这个连接执行任何(有含义)的语句,这个连接对于 MySQL 而言就处于 sleep,当 sleep 了太久,MySQL 就把连接一头关闭了(可能说了句 "啥玩意儿"),这时,如果 sqlalchemy 在这个连接上尝试执行语句,就会出现 gone away 的错误。

                                                                                                                                                                                                    

解决方法

设置 SQLAlchemy 的连接有效期,在 MySQL 关闭它之前,我先关闭它
因为 scoped_session 是 threadlocal 的,相同线程会用到相同的 session,如果 session 还持有 connection,从 pool 里 checkout connection 时不会进行过期的检查操作,直接使用,所以必须设置 SQLAIchemy 的有效期
SQLAlchemy 连接池重新生成的周期默认为 timeout 是 2 小时,通过  SHOW VARIABLES 可以查看数据库配置的 timeout 时间(如下图所示),所以设置 sqlalchemy 的 "pool_recycle" 参数小于 360s,就会在数据库服务器断开连接之前,自己断开并重新生成连接,

 
在 Web 框架的层面,每次请求处理完毕时,显式地关闭 session。

a. web 框架显示关闭 session 的方法有很多,常规方法如下, 在 finally 中主动关闭 seession

b. Django 和 Flask 都有 middleware 机制,可以在接收请求之前和处理完请求之后对 session 进行 remove
c. Flask 有一类修饰器 hook,可以在请求后或请求前做一些事情,使用 hook 显示关闭 session 如下

  了解其他 hook 修饰器戳:

before_first_request: 注册一个函数, 在处理第一个请求之前运行。
before_request: 注册一个函数, 在每次请求之前运行。
after_request: 注册一个函数, 如果没有未处理的异常抛出, 在每次请求之后运行。
teardown_request: 注册一个函数, 即使有未处理的异常抛出, 也在每次请求之后运行。
在使用 session 之前,先检查其有效性,无效则创建新的 session 以供使用
          

           

二、(2013  lost connection to mysql server during query)
 

 一般由以下四种情况造成, 通过 SHOW VARIABLES LIKE ‘’查看一下字段:

 

1、查询中大量数据被发送,由于数据传输时间不够导致,可以增加 net_read_timeout 的值。

net_read_timeout : mysql 服务端从客户端读取(接收)数据时,服务端等待客户端响应的超时时间,当服务端正在从客户端读取数据时,net_read_timeout 控制何时超时

2、初次连接时,连接时间设定太少,可以增加 connect_timeout 的值改善。

connect_timeout:在获取连接阶段(authenticate)起作用, 获取 MySQL 连接是多次握手的结果,除了用户名和密码的匹配校验外,还有 IP->HOST->DNS->IP 验证,任何一步都可能因为网络问题导致线程阻塞。为 了防止线程浪费在不必要的校验等待上,超过 connect_timeout 的连接请求将会被拒绝。

3、有些少见的情况可以 show global status like ‘aborted_connets’,这个全局变量在每一次服务器终止时会增加 1,查看 "reading authorization packet" 获取错误信息。

4、BLOB 值太大的问题,调整配置文件 max_allowed_packet。

mysql 根据配置文件会限制 server 接受的数据包大小。有时候大的插入和更新会被 max_allowed_packet 参数限制掉,导致失败。

三、keyError(dict 的 key 值不存在)
Python- 操作 dict 时避免出现 KeyError 的几种方法

四、TypeError(方法接收的类型不符)
错误原因
对无效类型的操作,即你操作的这个类型可能为空或者不符合接收函数参数的类型,就无法执行
解决方法
如下面使用 float 函数使用异常捕捉避免 TypeError

五、AttributeError(‘NoneType’ object has no attribute ’get’ )
      这种错误一般是由于调用对象为空,或者此对象没有对应的 attribute
————————————————
版权声明:本文为 CSDN 博主「TerryZjl」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dream_1996/article/details/83216018