General error: 2006 MySQL server has gone away

  • 错误原因
  • 制造错误
  • 解决办法
  • 最新办法

错误原因

Mysql has gone away

  1. MySQL 服务宕了
  2. mysql连接超时 show global variables like ‘%timeout’;
  3. mysql请求链接进程被主动kill show global status like ‘com_kill’;
  4. Your SQL statement was too large. show global variables like ‘max_allowed_packet’;

制造错误

造一个表

  1. -- ----------------------------
  2. -- Table structure for t_biubiu
  3. -- ----------------------------
  4. DROP TABLE IF EXISTS `t_biubiu`;
  5. CREATE TABLE `t_biubiu` (
  6. `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  7. `value` varchar(255) DEFAULT NULL,
  8. PRIMARY KEY (`id`)
  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

然后造一个程序

  1. public function actionInsert(){
  2. Biubiu::model()->findAll();
  3. $result = Yii::app()->db->createCommand("show global variables like '%timeout'")->queryAll();
  4. self::show_vars($result);
  5. for($index = 1 ;$index< 10;$index++){
  6. $model_ = new Biubiu();
  7. $model_->value = "insert".$index;
  8. if($index == 8){
  9. sleep(31);
  10. }
  11. $model_->save();
  12. }
  13. $model = new Biubiu();
  14. $model->value = "insert4";
  15. $model->save();
  16. }

设置你的MYSQL的wait_timeout = 30,interactive_timeout也要设置,否则不生效

执行的时候就会抛异常:

  1. exception 'CDbException' with message 'CDbCommand failed to execute the SQL statement: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away. The SQL statement executed was: INSERT INTO `t_biubiu` (`value`) VALUES (:yp0). Bound with :yp0='insert8'' in E:\phpWorks\framework\db\CDbCommand.php:362

sleep有效果了。

大部分情况就是超时导致的,尤其是脚本执行时间太长

解决办法

如果运维不同意 改变wait_timeout的值:

方法 做法
1 wait_timeout改大一些,并不能一劳永逸
2 代码中遇到超时重连
3 检查是不是Mysql连接过多,并发太高,忘记释放连接

解决方法推荐

例如,读写分离的 JDbConnection。在调用save delete方法的时候执行ensureActive() 。注意 @,否则异常发生的时候PHP ERROR直接挂掉。

  1. <?php
  2. /**
  3. * JDbConnection(Database Connection Manager) class is a manager of database connections.
  4. *
  5. * for the purpose of database read/write splitting.
  6. * It override the createCommand method,
  7. * detect the sql statement to decide which connection will be used.
  8. * Default it use the master connection.
  9. *
  10. */
  11. class JDbConnection extends CDbConnection
  12. {
  13. /**
  14. * @var array $slaves.Slave database connection(Read) config array.
  15. * The array value's format is the same as CDbConnection.
  16. * <code>
  17. * 'components'=>array(
  18. * 'db'=>array(
  19. * 'class' => 'JDbConnection',
  20. * 'connectionString'=>'MySQL://<master>',
  21. * 'slaves'=>array(
  22. * array('connectionString'=>'mysql://<slave01>'),
  23. * array('connectionString'=>'mysql://<slave02>'),
  24. * )
  25. * )
  26. * )
  27. * </code>
  28. */
  29. public $slaves = array();
  30. /**
  31. * Whether enable the slave database connection.
  32. * Defaut is true.Set this property to false for the purpose of only use the master database.
  33. *
  34. * @var bool $enableSlave
  35. */
  36. public $enableSlave = true;
  37. /**
  38. * @var CDbConnection
  39. */
  40. private $_slave;
  41. /**
  42. * Creates a CDbCommand object for excuting sql statement.
  43. * It will detect the sql statement's behavior.
  44. * While the sql is a simple read operation.
  45. * It will use a slave database connection to contruct a CDbCommand object.
  46. * Default it use current connection(master database).
  47. *
  48. * @override
  49. * @param string $sql
  50. * @return CDbCommand
  51. */
  52. public function createCommand($query = null)
  53. {
  54. if ($this->enableSlave && !$this->getCurrentTransaction() && self::isReadOperation($query)) {
  55. return $this->getSlave()->createCommand($query);
  56. } else {
  57. return parent::createCommand($query);
  58. }
  59. }
  60. /**
  61. * Construct a slave connection CDbConnection for read operation.
  62. *
  63. * @return CDbConnection
  64. */
  65. public function getSlave()
  66. {
  67. if (!isset($this->_slave)) {
  68. foreach ($this->slaves as $slaveConfig) {
  69. if (!isset($slaveConfig['class']))
  70. $slaveConfig['class'] = 'CDbConnection';
  71. try {
  72. if ($slave = Yii::createComponent($slaveConfig)) {
  73. Yii::app()->setComponent('dbslave', $slave);
  74. $this->_slave = $slave;
  75. break;
  76. }
  77. } catch (Exception $e) {
  78. Yii::log('Create slave database connection failed!', 'warn');
  79. continue;
  80. }
  81. }
  82. if (!$this->_slave) {
  83. $this->_slave = clone $this;
  84. $this->_slave->enableSlave = false;
  85. }
  86. }
  87. return $this->_slave;
  88. }
  89. /**
  90. * Detect whether the sql statement is just a simple read operation.
  91. * Read Operation means this sql will not change any thing ang aspect of the database.
  92. * Such as SELECT,DECRIBE,SHOW etc.
  93. * On the other hand:UPDATE,INSERT,DELETE is write operation.
  94. *
  95. * @return bool
  96. */
  97. public function isReadOperation($sql)
  98. {
  99. return !!preg_match('/^\s*(SELECT|SHOW|DESCRIBE|PRAGMA)/i', $sql);
  100. }
  101. /**
  102. * 确保数据库连接有效
  103. *
  104. * @params bool $isSlaveping主库还是从库
  105. * @return void
  106. */
  107. public function ensureActive($isSlave = true)
  108. {
  109. if ($this->getActive()) {
  110. try {
  111. @$this->getPdoInstance()->query('SELECT 1');
  112. } catch (PDOException $e) {
  113. $this->setActive(false);
  114. $this->setActive(true);
  115. }
  116. }
  117. }
  118. }

调用示例:

  1. Yii::app()->db->ensureActive();

另外一种方法

执行SQL之前执行:

  1. Yii::$app->db->createCommand('SET SESSION wait_timeout = 28800;')->execute();

最新办法

避免每次多请求了一次数据库。只有在遇到问题时进入异常处理,重试的时候Yii会自动进行重连[不确定]。

  1. public static function retry($params, $call){
  2. for($retry = 0; $retry < 3;$retry++){
  3. try{
  4. if($params instanceof CModel){
  5. return $params->$call();
  6. }
  7. }catch(CDbException $e){
  8. if (!(strpos($e, "error: 2006") && !strpos($e, "error: 2013"))) {
  9. throw new Exception($e->getMessage(), 520);
  10. }
  11. }
  12. }
  13. return false;
  14. }

2017年4月9日 更新

最近发现,公司所用的yii framework1.1的框架,和官方下载的不太一样。

下载最新框架,测试代码如下,我将mysql设置为wait_timeout=30, interactive_timeout=30

  1. class DbTestCommand extends CConsoleCommand {
  2. public function actionInsert(){
  3. $sql = "insert into adv_pro ( `name` , `int_value`) values ('insert', 100)";
  4. Yii::app()->localdb->createCommand($sql)->execute();
  5. sleep(31);
  6. $sql = "insert into adv_pro ( `name` , `int_value`) values ('insert', 200)";
  7. Yii::app()->localdb->createCommand($sql)->execute();
  8. }
  9. }

结果就出现了:

  1. PHP Error[2]: PDOStatement::execute(): MySQL server has gone away
  2. in file D:\work_project\framework\db\CDbCommand.php at line 336
  3. #0 D:\work_project\framework\db\CDbCommand.php(336): PDOStatement->execute()
  4. #1 D:\work_project\task\protected\commands\DbTestCommand.php(19): CDbCommand->execute()
  5. #2 unknown(0): DbTestCommand->actionInsert()

再加上@符号抑制错误

  1. @Yii::app()->localdb->createCommand($sql)->execute();

结果异常就抛出来了:

  1. exception 'CDbException' with message 'CDbCommand failed to execute the SQL statement: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away. The SQL statement executed was: insert into adv_pro ( `name` , `int_value`) values ('insert', 200)' in D:\work_project\framework\db\CDbCommand.php:363
  2. Stack trace:
  3. #0 D:\work_project\task\protected\commands\DbTestCommand.php(19): CDbCommand->execute()

那么可以把框架的db/CDbCommand.php内的execute方法改一下,改成:

  1. if($params===array())
  2. @$this->_statement->execute();
  3. else
  4. @$this->_statement->execute($params);

这样就能捕获到这个异常了。

那么据此,可以为CDbCommand.php增加一个方法:

  1. public function sqlDbExecute($params=array()){
  2. $e = new Exception("sqlDbExecute failed three times", 10001);
  3. for ($count=0;$count<3;$count++){
  4. try {
  5. $result = $this->execute($params);
  6. return $result;
  7. } catch (Exception $e) {
  8. Yii::log('Error in sqlDbExecute SQL: '.$this->getText(),CLogger::LEVEL_ERROR,'system.db.CDbCommand');
  9. $this->_connection->setActive(true);
  10. //If not found 2006 then throw up
  11. if (!strpos($e, "error: 2006")) {
  12. throw new Exception($e,10001);
  13. }
  14. }
  15. }
  16. throw new Exception($e,10001);
  17. }

Yii 数据库重连告别General error: 2006 MySQL server has gone away的更多相关文章

  1. ThinkPHP出现General error: 2006 MySQL server has gone away的解决方法

    错误: #13 {main}SQLSTATE[HY000]: General error: 2006 MySQL server has gone awayFILE: \ThinkPHP\Library ...

  2. General error 2006 MySQL server has gone away

    写入配置文件的办法: max_allowed_packet = 16M //但是这种有时候不支持,1024*1024*16这种有的也不支持 max_allowed_packet = 16777216 ...

  3. flask+mako+peewee(下)(解决了Error 2006: MySQL server has gone away)

    这篇主要介绍在这次项目中使用的peewee 文档地址:http://peewee.readthedocs.org/en/latest/index.html 首先我们要初始化一个数据库连接对象.这里我使 ...

  4. mysql error: (2006, 'MySQL server has gone away')

    max_allowed_packet=16M wait_timeout= interactive_timeout = vim /etc/my.cnf  mysqld 中加入上面的内容.

  5. MySql General error:2006

    当启用模块时发生Mysql数据库错误,错误信息见附件,实际是“General error: 2006 MySQL server has gone away......”错误. 解决方法:找到my.in ...

  6. 2006 - MySQL server has gone away

    mysql出现ERROR : (2006, 'MySQL server has gone away') 的问题意思就是指client和MySQL server之间的链接断开了. 造成这样的原因一般是s ...

  7. SQLyog恢复数据库报错解决方法【Error Code: 2006 - MySQL server has gone away】

    https://blog.csdn.net/niqinwen/article/details/8693044 导入数据库的时候 SQLyog 报错了 Error Code: 2006 – MySQL ...

  8. MYSQL导入数据报错|MYSQL导入超大文件报错|MYSQL导入大数据库报错:2006 - MySQL server has gone away

    导SQL数据库结构+数据时,如果数据是批量插入的话会报错:2006 - MySQL server has gone away. 解决办法:找到你的mysql目录下的my.ini配置文件(如果安装目录没 ...

  9. Yii2 解决2006 MySQL server has gone away问题

    Yii2 解决2006 MySQL server has gone away问题 Yii2版本 2.0.15.1 php后台任务经常包含多段sql,如果php脚本执行时间较长,或者sql执行时间较长, ...

随机推荐

  1. (七十五)c#Winform自定义控件-控件水印组件

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  2. Python学习-列表元组字典操作

    一.列表 列表是Python的基本数据类型之一,它是以 [] 括起来的,内部成员用逗号隔开.里面可以存放各种数据类型. # 例如: list2 = ['jason', 2, (1, 3), ['war ...

  3. python2.7过渡到python3.6时遇到的差异总结

    1.Python3中print为一个函数,必须用括号括起来而Python2中print为class print('hello') 2.python3将raw_input和input进行了整合,只有in ...

  4. Java源码跟踪阅读技巧

    转:https://www.jianshu.com/p/ab865109070c 本文基于Eclipse IDE 1.Quick Type Hierarchy 快速查看类继承体系. 快捷键:Ctrl ...

  5. 创建FTP访问的YUM源

    创建FTP访问的YUM源 一.安装vsftpd(步骤详见“在linux中搭建vsftpd.docx”) 在主机A上安装FTP,安装后的ftp信息如下:ftp://192.168.43.300  账号密 ...

  6. eShopOnContainers学习系列(二):数据库连接健康检查

    项目里使用数据库的时候,我们有时候需要知道数据库当前的健康状态,特别是当数据库连接不上的时候能够立马获悉.eShopOnContainers里存在着大量的服务健康.连接健康的检查,数据库连接是其中之一 ...

  7. maven打包工程出现错误 Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test

    今天用maven在命令行打包项目的时候出现错误: Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12. ...

  8. 高清屏下canvas重置尺寸引发的问题

    我们知道,清空canvas画布内容有以下两个方法. 第一种方法是cearRect函数: context.cearRect(0,0,canvas.width,canvas.height) 第二种方法就是 ...

  9. js中的toString和valueOf

    数据的转换 基本上,所有JS数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题 所有对象继承了两个转换方法: 第一个是toStri ...

  10. 各种常见文件的hex文件头

    我们在做ctf时,经常需要辨认各种文件头,跟大家分享一下一些常见的文件头.   扩展名 文件头标识(HEX) 文件描述 123 00 00 1A 00 05 10 04 Lotus 1-2-3 spr ...