PHP連接MySql閃斷自動重連的方法

使用php作為后臺運行程序(例如短信群發(fā))梧躺,在cli模式下執(zhí)行php,php需要連接mysql循環(huán)執(zhí)行數(shù)據(jù)庫處理傲绣。

當(dāng)mysql連接閃斷時掠哥,之后循環(huán)的執(zhí)行將會失敗。

我們需要設(shè)計一個方法秃诵,當(dāng)mysql閃斷時续搀,可以自動重新連接,使后面的程序可以正常執(zhí)行下去菠净。

1.創(chuàng)建測試數(shù)據(jù)表

CREATE TABLE `user` (

`id` int(11) unsigned NOT NULL AUTO_INCREMENT,

`name` varchar(20) NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2.插入測試數(shù)據(jù)

insert into user(name) values('fdipzone'),('xfdipzone'),('terry');

mysql> select * from user;

+----+-----------+

| id | name |

+----+-----------+

| 1 | fdipzone |

| 2 | xfdipzone |

| 3 | terry |

+----+-----------+

3.后臺運行的php文件

db.php

<?php

// 數(shù)據(jù)庫操作類

class DB{

// 保存數(shù)據(jù)庫連接

private static $_instance = null;

// 連接數(shù)據(jù)庫

public static function get_conn($config){if(isset(self::$_instance) && !empty(self::$_instance)){

return self::$_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] = 'SET NAMES ' . $charset; //設(shè)置默認編碼

}

if ($pconnect) {

$h_param[PDO::ATTR_PERSISTENT] = true;

}

$conn = new PDO($dsn, $dbuser, $dbpasswd, $h_param);

} catch (PDOException $e) {

throw new ErrorException('Unable to connect to db server. Error:' . $e->getMessage(), 31);

}

self::$_instance = $conn;

return $conn;

}

// 執(zhí)行查詢

public static function query($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';

// 數(shù)據(jù)庫設(shè)定

$config = array(

'host' => 'localhost',

'dbname' => 'user',

'user' => 'root',

'password' => '',

'pconnect' => 0,

'charset' => ''

);

// 循環(huán)執(zhí)行

while(true){

// 創(chuàng)建數(shù)據(jù)連接

$dbconn = DB::get_conn($config);

// 執(zhí)行查詢

$sqlstr = 'select * from user where id=?';

$condparam = array(mt_rand(1,3));

$data = DB::query($dbconn, $sqlstr, $condparam);

print_r($data);

// 延時10秒

echo 'sleep 10'.PHP_EOL.PHP_EOL;

sleep(10);

}

?>

4.執(zhí)行步驟

在php cli模式下執(zhí)行test.php禁舷,然后馬上執(zhí)行mysql.server stop 與 mysql.server start 模擬閃斷

mysql.server stop

Shutting down MySQL

.. SUCCESS!

mysql.server start

Starting MySQL

SUCCESS!

可以看到,閃斷后不能重新連接數(shù)據(jù)庫毅往,后面的程序不能執(zhí)行下去牵咙。

Array

(

[0] => Array

(

[id] => 3

[name] => terry

)

)

sleep 10

SQLSTATE[HY000]: General error: 2006 MySQL server has gone away

Array

(

)

sleep 10

SQLSTATE[HY000]: General error: 2006 MySQL server has gone away

Array

(

)

sleep 10

...

5.增加重連機制

if(isset(self::$_instance) && !empty(self::$_instance)){

return self::$_instance;

}

閃斷后,因為 self::$_instance 的值存在攀唯,因此調(diào)用get_conn并不會重新連接洁桌,而是使用保存的連接進行處理。

這樣實際上是當(dāng)連接存在時革答,不需要再次創(chuàng)建mysql連接战坤,減少mysql連接數(shù)。

所以需要在閃斷后残拐,清空self::$_instance的值,使下次重新獲取連接碟嘴,而不使用已經(jīng)創(chuàng)建但失效的數(shù)據(jù)庫連接溪食。

改進方法如下:

增加reset_connect方法,當(dāng)出現(xiàn)錯誤時調(diào)用娜扇。如果判斷錯誤是MySQL server has gone away則清空已經(jīng)存在的數(shù)據(jù)庫連接错沃,清空后下次則會重新連接mysql。

修改后的php文件如下:

db.php

<?php

// 數(shù)據(jù)庫操作類

class DB{

// 保存數(shù)據(jù)庫連接

private static $_instance = null;

// 連接數(shù)據(jù)庫

public static function get_conn($config){if(isset(self::$_instance) && !empty(self::$_instance)){

return self::$_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] = 'SET NAMES ' . $charset; //設(shè)置默認編碼

}

if ($pconnect) {

$h_param[PDO::ATTR_PERSISTENT] = true;

}

$conn = new PDO($dsn, $dbuser, $dbpasswd, $h_param);

} catch (PDOException $e) {

throw new ErrorException('Unable to connect to db server. Error:' . $e->getMessage(), 31);

}

self::$_instance = $conn;

return $conn;

}

// 執(zhí)行查詢

public static function query($dbconn, $sqlstr, $condparam){

$sth = $dbconn->prepare($sqlstr);

try{

$sth->execute($condparam);

} catch (PDOException $e) {

echo $e->getMessage().PHP_EOL;

self::reset_connect($e->getMessage()); // 出錯時調(diào)用重置連接

}

$result = $sth->fetchAll(PDO::FETCH_ASSOC);

return $result;

}

// 重置連接

public static function reset_connect($err_msg){

if(strpos($err_msg, 'MySQL server has gone away')!==false){

self::$_instance = null;

}

}

}

?>

6.再次進行閃斷執(zhí)行

可以看到改進后的效果雀瓢,閃斷后枢析,當(dāng)前執(zhí)行的會失敗,但之后的可以重新創(chuàng)建新連接繼續(xù)執(zhí)行下去刃麸。

Array

(

[0] => Array

(

[id] => 2

[name] => xfdipzone

)

)

sleep 10

SQLSTATE[HY000]: General error: 2006 MySQL server has gone away

Array

(

)

sleep 10

Array

(

[0] => Array

(

[id] => 1

[name] => fdipzone

)

)

sleep 10

...


文章同步發(fā)布:?https://www.geek-share.com/detail/2683442734.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末醒叁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌把沼,老刑警劉巖啊易,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異饮睬,居然都是意外死亡租谈,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門捆愁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來割去,“玉大人,你說我怎么就攤上這事昼丑∩肽妫” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵矾克,是天一觀的道長页慷。 經(jīng)常有香客問我,道長胁附,這世上最難降的妖魔是什么酒繁? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮控妻,結(jié)果婚禮上州袒,老公的妹妹穿的比我還像新娘。我一直安慰自己弓候,他們只是感情好郎哭,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著菇存,像睡著了一般夸研。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上依鸥,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天亥至,我揣著相機與錄音,去河邊找鬼贱迟。 笑死姐扮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的衣吠。 我是一名探鬼主播茶敏,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼缚俏!你這毒婦竟也來了惊搏?” 一聲冷哼從身側(cè)響起贮乳,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎胀屿,沒想到半個月后塘揣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡宿崭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年亲铡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葡兑。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡奖蔓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出讹堤,到底是詐尸還是另有隱情吆鹤,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布洲守,位于F島的核電站疑务,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏梗醇。R本人自食惡果不足惜知允,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望叙谨。 院中可真熱鬧温鸽,春花似錦、人聲如沸手负。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽竟终。三九已至蝠猬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間统捶,已是汗流浹背吱雏。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瘾境,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓镰惦,卻偏偏與公主長得像迷守,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子旺入,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容