PHP连接MySql闪断自动重连的方法
使用php作为后台运行程序(例如短信群发),在cli模式下执行php,php需要连接mysql循环执行数据库处理。
当mysql连接闪断时,之后循环的执行将会失败。
我们需要设计一个方法,当mysql闪断时,可以自动重新连接,使后面的程序可以正常执行下去。
1.创建测试数据表
CREATETABLE`user`( `id`int(11)unsignedNOTNULLAUTO_INCREMENT, `name`varchar(20)NOTNULL, PRIMARYKEY(`id`) )ENGINE=InnoDBDEFAULTCHARSET=utf8;
2.插入测试数据
insertintouser(name)values('fdipzone'),('xfdipzone'),('terry');
mysql>select*fromuser;
+----+-----------+
|id|name|
+----+-----------+
|1|fdipzone|
|2|xfdipzone|
|3|terry|
+----+-----------+
3.后台运行的php文件
db.php
<?php
//数据库操作类
classDB{
//保存数据库连接
privatestatic$_instance=null;
//连接数据库
publicstaticfunctionget_conn($config){
if(isset(self::$_instance)&&!empty(self::$_instance)){
returnself::$_instance;
}
$dbhost=$config['host'];
$dbname=$config['dbname'];
$dbuser=$config['user'];
$dbpasswd=$config['password'];
$pconnect=$config['pconnect'];
$charset=$config['charset'];
$dsn="mysql:host=$dbhost;dbname=$dbname;";
try{
$h_param=array(
PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,
);
if($charset!=''){
$h_param[PDO::MYSQL_ATTR_INIT_COMMAND]='SETNAMES'.$charset;//設置默認編碼
}
if($pconnect){
$h_param[PDO::ATTR_PERSISTENT]=true;
}
$conn=newPDO($dsn,$dbuser,$dbpasswd,$h_param);
}catch(PDOException$e){
thrownewErrorException('Unabletoconnecttodbserver.Error:'.$e->getMessage(),31);
}
self::$_instance=$conn;
return$conn;
}
//执行查询
publicstaticfunctionquery($dbconn,$sqlstr,$condparam){
$sth=$dbconn->prepare($sqlstr);
try{
$sth->execute($condparam);
}catch(PDOException$e){
echo$e->getMessage().PHP_EOL;
}
$result=$sth->fetchAll(PDO::FETCH_ASSOC);
return$result;
}
}
?>
test.php
<?php
require'db.php';
//数据库设定
$config=array(
'host'=>'localhost',
'dbname'=>'user',
'user'=>'root',
'password'=>'',
'pconnect'=>0,
'charset'=>''
);
//循环执行
while(true){
//创建数据连接
$dbconn=DB::get_conn($config);
//执行查询
$sqlstr='select*fromuserwhereid=?';
$condparam=array(mt_rand(1,3));
$data=DB::query($dbconn,$sqlstr,$condparam);
print_r($data);
//延时10秒
echo'sleep10'.PHP_EOL.PHP_EOL;
sleep(10);
}
?>
4.执行步骤
在phpcli模式下执行test.php,然后马上执行mysql.serverstop与mysql.serverstart模拟闪断
mysql.serverstop ShuttingdownMySQL ..SUCCESS! mysql.serverstart StartingMySQL SUCCESS!
可以看到,闪断后不能重新连接数据库,后面的程序不能执行下去。
Array ( [0]=>Array ( [id]=>3 [name]=>terry ) ) sleep10 SQLSTATE[HY000]:Generalerror:2006MySQLserverhasgoneaway Array ( ) sleep10 SQLSTATE[HY000]:Generalerror:2006MySQLserverhasgoneaway Array ( ) sleep10 ...
5.增加重连机制
if(isset(self::$_instance)&&!empty(self::$_instance)){
returnself::$_instance;
}
闪断后,因为self::$_instance的值存在,因此调用get_conn并不会重新连接,而是使用保存的连接进行处理。
这样实际上是当连接存在时,不需要再次创建mysql连接,减少mysql连接数。
所以需要在闪断后,清空self::$_instance的值,使下次重新获取连接,而不使用已经创建但失效的数据库连接。
改进方法如下:
增加reset_connect方法,当出现错误时调用。如果判断错误是MySQLserverhasgoneaway则清空已经存在的数据库连接,清空后下次则会重新连接mysql。
修改后的php文件如下:
db.php
<?php
//数据库操作类
classDB{
//保存数据库连接
privatestatic$_instance=null;
//连接数据库
publicstaticfunctionget_conn($config){
if(isset(self::$_instance)&&!empty(self::$_instance)){
returnself::$_instance;
}
$dbhost=$config['host'];
$dbname=$config['dbname'];
$dbuser=$config['user'];
$dbpasswd=$config['password'];
$pconnect=$config['pconnect'];
$charset=$config['charset'];
$dsn="mysql:host=$dbhost;dbname=$dbname;";
try{
$h_param=array(
PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,
);
if($charset!=''){
$h_param[PDO::MYSQL_ATTR_INIT_COMMAND]='SETNAMES'.$charset;//設置默認編碼
}
if($pconnect){
$h_param[PDO::ATTR_PERSISTENT]=true;
}
$conn=newPDO($dsn,$dbuser,$dbpasswd,$h_param);
}catch(PDOException$e){
thrownewErrorException('Unabletoconnecttodbserver.Error:'.$e->getMessage(),31);
}
self::$_instance=$conn;
return$conn;
}
//执行查询
publicstaticfunctionquery($dbconn,$sqlstr,$condparam){
$sth=$dbconn->prepare($sqlstr);
try{
$sth->execute($condparam);
}catch(PDOException$e){
echo$e->getMessage().PHP_EOL;
self::reset_connect($e->getMessage());//出错时调用重置连接
}
$result=$sth->fetchAll(PDO::FETCH_ASSOC);
return$result;
}
//重置连接
publicstaticfunctionreset_connect($err_msg){
if(strpos($err_msg,'MySQLserverhasgoneaway')!==false){
self::$_instance=null;
}
}
}
?>
6.再次进行闪断执行
可以看到改进后的效果,闪断后,当前执行的会失败,但之后的可以重新创建新连接继续执行下去。
Array ( [0]=>Array ( [id]=>2 [name]=>xfdipzone ) ) sleep10 SQLSTATE[HY000]:Generalerror:2006MySQLserverhasgoneaway Array ( ) sleep10 Array ( [0]=>Array ( [id]=>1 [name]=>fdipzone ) ) sleep10 ...
以上所述是小编给大家介绍的PHP连接MySql闪断自动重连的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!