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’;

制造错误

造一个表

-- ----------------------------
-- Table structure for t_biubiu
-- ----------------------------
DROP TABLE IF EXISTS `t_biubiu`;
CREATE TABLE `t_biubiu` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`value` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

然后造一个程序

public function actionInsert(){
Biubiu::model()->findAll();
$result = Yii::app()->db->createCommand("show global variables like '%timeout'")->queryAll();
self::show_vars($result);
for($index = 1 ;$index< 10;$index++){
$model_ = new Biubiu();
$model_->value = "insert".$index;
if($index == 8){
sleep(31);
}
$model_->save();
}
$model = new Biubiu();
$model->value = "insert4";
$model->save();
}

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

执行的时候就会抛异常:

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直接挂掉。

<?php

/**
* JDbConnection(Database Connection Manager) class is a manager of database connections.
*
* for the purpose of database read/write splitting.
* It override the createCommand method,
* detect the sql statement to decide which connection will be used.
* Default it use the master connection.
*
*/
class JDbConnection extends CDbConnection
{
/**
* @var array $slaves.Slave database connection(Read) config array.
* The array value's format is the same as CDbConnection.
* <code>
* 'components'=>array(
* 'db'=>array(
* 'class' => 'JDbConnection',
* 'connectionString'=>'MySQL://<master>',
* 'slaves'=>array(
* array('connectionString'=>'mysql://<slave01>'),
* array('connectionString'=>'mysql://<slave02>'),
* )
* )
* )
* </code>
*/
public $slaves = array(); /**
* Whether enable the slave database connection.
* Defaut is true.Set this property to false for the purpose of only use the master database.
*
* @var bool $enableSlave
*/
public $enableSlave = true; /**
* @var CDbConnection
*/
private $_slave; /**
* Creates a CDbCommand object for excuting sql statement.
* It will detect the sql statement's behavior.
* While the sql is a simple read operation.
* It will use a slave database connection to contruct a CDbCommand object.
* Default it use current connection(master database).
*
* @override
* @param string $sql
* @return CDbCommand
*/
public function createCommand($query = null)
{
if ($this->enableSlave && !$this->getCurrentTransaction() && self::isReadOperation($query)) {
return $this->getSlave()->createCommand($query);
} else {
return parent::createCommand($query);
}
} /**
* Construct a slave connection CDbConnection for read operation.
*
* @return CDbConnection
*/
public function getSlave()
{
if (!isset($this->_slave)) {
foreach ($this->slaves as $slaveConfig) {
if (!isset($slaveConfig['class']))
$slaveConfig['class'] = 'CDbConnection';
try {
if ($slave = Yii::createComponent($slaveConfig)) {
Yii::app()->setComponent('dbslave', $slave);
$this->_slave = $slave;
break;
}
} catch (Exception $e) {
Yii::log('Create slave database connection failed!', 'warn');
continue;
}
}
if (!$this->_slave) {
$this->_slave = clone $this;
$this->_slave->enableSlave = false;
}
}
return $this->_slave;
} /**
* Detect whether the sql statement is just a simple read operation.
* Read Operation means this sql will not change any thing ang aspect of the database.
* Such as SELECT,DECRIBE,SHOW etc.
* On the other hand:UPDATE,INSERT,DELETE is write operation.
*
* @return bool
*/
public function isReadOperation($sql)
{
return !!preg_match('/^\s*(SELECT|SHOW|DESCRIBE|PRAGMA)/i', $sql);
} /**
* 确保数据库连接有效
*
* @params bool $isSlaveping主库还是从库
* @return void
*/
public function ensureActive($isSlave = true)
{
if ($this->getActive()) {
try {
@$this->getPdoInstance()->query('SELECT 1');
} catch (PDOException $e) {
$this->setActive(false);
$this->setActive(true);
}
}
}
}

调用示例:

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

另外一种方法

执行SQL之前执行:

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

最新办法

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

public static function retry($params, $call){
for($retry = 0; $retry < 3;$retry++){
try{
if($params instanceof CModel){
return $params->$call();
}
}catch(CDbException $e){
if (!(strpos($e, "error: 2006") && !strpos($e, "error: 2013"))) {
throw new Exception($e->getMessage(), 520);
}
}
}
return false;
}

2017年4月9日 更新

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

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

class DbTestCommand extends CConsoleCommand {

    public function actionInsert(){

        $sql = "insert into adv_pro ( `name` , `int_value`) values ('insert', 100)";
Yii::app()->localdb->createCommand($sql)->execute();
sleep(31);
$sql = "insert into adv_pro ( `name` , `int_value`) values ('insert', 200)";
Yii::app()->localdb->createCommand($sql)->execute(); } }

结果就出现了:

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

再加上@符号抑制错误

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

结果异常就抛出来了:

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
Stack trace:
#0 D:\work_project\task\protected\commands\DbTestCommand.php(19): CDbCommand->execute()

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

if($params===array())
@$this->_statement->execute();
else
@$this->_statement->execute($params);

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

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

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

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. jenkins插件之Publish Over SSH的使用

    1,安装 在插件管理选项搜索Publish Over SSH,然后点击安装即可完成 2,安装完成之后,就可以在jenkins的配置系统中找到Publish Over SSH 配置完服务器之后,然后在项 ...

  2. Spring 梳理-使用<context:property-placeholder>标签导入多个properties文件

    使用<context:property-placeholder>标签导入多个properties文件 2017年12月20日 10:10:36 sf_climber 阅读数:5830更多 ...

  3. _self.$scopedSlots.default is not a function报错

    问题: 当同一页面有elementUI的多个table表格时,如果用到v-if来动态展示表格,切换时出现如下报错: 原因: 是因为表格是element-ui通过循环产生的,而vue在dom重新渲染时有 ...

  4. Java 学习笔记之 实例变量非线程安全

    实例变量非线程安全: 如果多个线程共同访问1个对象中的实例变量,则可能出现“非线程安全”问题. public class UnSafeHasSelfPrivateNum { private int n ...

  5. c++ 对特定进程的内存监控

    在工具实现的过程中,遇到了内存爆了的问题,部分模型的规模可以达到10的100次方方甚至1000次方.(工具的主要算法涉及到了递归,递归深度会很深,所以也用到了ulimit修改栈空间来缓解爆栈的问题,治 ...

  6. Spring使用ThreadPoolTaskExecutor自定义线程池及实现异步调用

    多线程一直是工作或面试过程中的高频知识点,今天给大家分享一下使用 ThreadPoolTaskExecutor 来自定义线程池和实现异步调用多线程. 一.ThreadPoolTaskExecutor ...

  7. 超详细的FreeRTOS移植全教程——基于srm32

    ### 准备 在移植之前,我们首先要获取到FreeRTOS的官方的源码包.这里我们提供两个下载链接: > 一个是官网:http://www.freertos.org/ > 另外一个是代码托 ...

  8. 单元测试实践(SpringCloud+Junit5+Mockito+DataMocker)

    网上看过一句话,单元测试就像早睡早起,每个人都说好,但是很少有人做到.从这么多年的项目经历亲身证明,是真的. 这次借着项目内实施单元测试的机会,记录实施的过程和一些总结经验. 项目情况 首先是背景,项 ...

  9. 微信小程序发起请求

    一.示例代码 wx.request({ url: 'test.php', // 仅为示例,并非真实的接口地址 data: { x: '', y: '' }, header: { 'content-ty ...

  10. docker配置阿里云镜像

    今天docker pull镜像的时候太慢了  所以这里配置下阿里云镜像 打开阿里云控制台,没有的可以用淘宝账号或者支付宝账号直接登录 打开容器镜像服务,镜像加速器,复制加速器地址 修改配置文件 $: ...