Lost connection to MySQL server 或者 MySQL server has gone away解决

前话

在工作中,有时候一些后台脚本需要长时间的运行,同时可能在连接数据库后,长时间不与数据库服务端交互。此时,服务器可能会断开与客户端的连接。从而客户端再次交互时就会出现""连接丢失。
此次修改达到的效果:断线重连机制对应用层完全透明,无需自己重复发送请求。

错误原因

Mysql has gone away 或者 Lost connection to MySQL server 或者 Error while sending QUERY packet

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

制造错误

造一个表

DROP TABLE IF EXISTS `nt_vm_message_idempotent`;
CREATE TABLE `nt_vm_message_idempotent` (
`uid` mediumint(15) NOT NULL DEFAULT 0,
`message_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '消息ID',
`message_content` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '消息内容',
`product_status` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否生产成功到mq',
`consume_status` tinyint(1) NOT NULL COMMENT '是否消费成功',
`create_time` int(10) UNSIGNED NOT NULL DEFAULT 0,
`update_time` int(10) UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`message_id`) USING BTREE,
UNIQUE INDEX `unique_message_id`(`message_id`) USING BTREE,
INDEX `uid`(`uid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

然后造一个程序

public function actionInsert(){
try{
          //设置你的MYSQL的wait_timeout = 30,interactive_timeout也要设置,否则不生效 为了测试
Yii::app()->db->createCommand('SET SESSION wait_timeout = 30;SET SESSION interactive_timeout = 30;')->execute();
$result = Yii::app()->db->createCommand("show global variables like '%timeout'")->queryAll();
print_r($result);
$sql = "insert into nt_vm_message_idempotent ( `uid` , `message_id` , `message_content` , `product_status`,`consume_status` , `create_time`, `update_time`) values
('98468', '100', 'asdfsda', 1,0,1,2)";
Yii::app()->db->createCommand($sql)->execute();
sleep(31);
$sql = "UPDATE nt_vm_message_idempotent SET consume_status=1,update_time=1623412774 WHERE message_id = '100'";
//再加上@符号抑制错误 要不下面捕捉不到
         @Yii::app()->db->createCommand($sql)->execute();
}catch (Exception $e){
echo $e->getMessage();
if(strpos($e->getMessage(),'UPDATE nt_vm_message_idempotent SET') !== false){
//yii重连数据库 需要解决这个问题需要打开注释
//Yii::app()->db->setActive(false);
$sql = "UPDATE nt_vm_message_idempotent SET consume_status=1,update_time=1623412774 WHERE message_id = '100'";
@Yii::app()->db->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 `t_biubiu` (`value`) VALUES (:yp0). Bound with :yp0='insert8'' in E:\phpWorks\framework\db\CDbCommand.php:362

sleep有效果了。

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

解决办法

方法 做法
1 在my.cnf里wait_timeout改大一些,并不能一劳永逸
2 代码中遇到超时重连 你需要在自己的PHP数据库连接处增加大致如下代码。

if( in_array(mysql_errno(), array(2006, 2013))){

        mysql_close();

        mysql_connect(...);

       mysql_query(...);

}

3 检查是不是Mysql连接过多,并发太高,忘记释放连接(一般出现这种情况不是所有例句而是单个表,请你先修复表一般都能解决这类问题。)  
上一篇:libco源码解析---read,write与条件变量


下一篇:K8s 节点断开连接后,本在运行的 Pod 会如何?