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闪断自动重连的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!