日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Yii 数据库重连告别General error: 2006 MySQL server has gone away

發(fā)布時(shí)間:2024/4/17 数据库 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Yii 数据库重连告别General error: 2006 MySQL server has gone away 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

General error: 2006 MySQL server has gone away

  • 錯(cuò)誤原因
  • 制造錯(cuò)誤
  • 解決辦法
  • 最新辦法

錯(cuò)誤原因

Mysql has gone away

  • MySQL 服務(wù)宕了
  • mysql連接超時(shí) show global variables like ‘%timeout’;
  • mysql請(qǐng)求鏈接進(jìn)程被主動(dòng)kill show global status like ‘com_kill’;
  • Your SQL statement was too large. show global variables like ‘max_allowed_packet’;
  • 制造錯(cuò)誤

    造一個(gè)表

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

    然后造一個(gè)程序

    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();}

    設(shè)置你的MYSQL的wait_timeout = 30,interactive_timeout也要設(shè)置,否則不生效

    執(zhí)行的時(shí)候就會(huì)拋異常:

    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有效果了。

    大部分情況就是超時(shí)導(dǎo)致的,尤其是腳本執(zhí)行時(shí)間太長

    解決辦法

    如果運(yùn)維不同意 改變wait_timeout的值:

    方法做法
    1wait_timeout改大一些,并不能一勞永逸
    2代碼中遇到超時(shí)重連
    3檢查是不是Mysql連接過多,并發(fā)太高,忘記釋放連接

    解決方法推薦

    例如,讀寫分離的 JDbConnection。在調(diào)用save delete方法的時(shí)候執(zhí)行ensureActive() 。注意 @,否則異常發(fā)生的時(shí)候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);}/*** 確保數(shù)據(jù)庫連接有效** @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);}}} }

    調(diào)用示例:

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

    另外一種方法

    執(zhí)行SQL之前執(zhí)行:

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

    最新辦法

    避免每次多請(qǐng)求了一次數(shù)據(jù)庫。只有在遇到問題時(shí)進(jìn)入異常處理,重試的時(shí)候Yii會(huì)自動(dòng)進(jìn)行重連[不確定]。

    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日 更新

    最近發(fā)現(xiàn),公司所用的yii framework1.1的框架,和官方下載的不太一樣。

    下載最新框架,測試代碼如下,我將mysql設(shè)置為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();}}

    結(jié)果就出現(xiàn)了:

    PHP Error[2]: PDOStatement::execute(): MySQL server has gone awayin 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()

    再加上@符號(hào)抑制錯(cuò)誤

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

    結(jié)果異常就拋出來了:

    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內(nèi)的execute方法改一下,改成:

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

    這樣就能捕獲到這個(gè)異常了。

    那么據(jù)此,可以為CDbCommand.php增加一個(gè)方法:

    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 upif (!strpos($e, "error: 2006")) {throw new Exception($e,10001);}}}throw new Exception($e,10001);}

    轉(zhuǎn)載于:https://www.cnblogs.com/slankka/p/9158512.html

    總結(jié)

    以上是生活随笔為你收集整理的Yii 数据库重连告别General error: 2006 MySQL server has gone away的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。