mysql接続が中断されたときに自動的に再接続する方法

jacklove
リリース: 2023-03-31 06:20:02
オリジナル
2322 人が閲覧しました

php をバックグラウンド実行プログラム (バルク SMS など) として使用し、php を cli モードで実行します。php はループでデータベース処理を実行するために mysql に接続する必要があります。
mysql 接続が中断されると、その後のループの実行は失敗します。

mysql が切断されたときに、後続のプログラムが正常に実行できるように、自動的に再接続できるメソッドを設計する必要があります。

1. テスト データ テーブルを作成します

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. テスト データを挿入します

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// 数据库操作类class DB{
    // 保存数据库连接
    private static $_instance = null;    // 连接数据库
    public static function get_conn($config){
        if(isset(self::$_instance) && !empty(self::$_instance)){            return self::$_instance;
        }        $dbhost = $config[&#39;host&#39;];        $dbname = $config[&#39;dbname&#39;];        $dbuser = $config[&#39;user&#39;];        $dbpasswd = $config[&#39;password&#39;];        $pconnect = $config[&#39;pconnect&#39;];        $charset = $config[&#39;charset&#39;];        $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; //設置默認編碼
            }            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;
    }    // 执行查询
    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

<?phprequire &#39;db.php&#39;;// 数据库设定$config = array(    &#39;host&#39; => 'localhost',    'dbname' => 'user',    'user' => 'root',    'password' => '',    'pconnect' => 0,    'charset' => '');// 循环执行while(true){    // 创建数据连接
    $dbconn = DB::get_conn($config);    // 执行查询
    $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 の手順 を実行します。 php cli モードで test.php を実行し、すぐに mysql.server stop と mysql.server start を実行してフラッシュ中断をシミュレートします

mysql.server stopShutting down MySQL
.. SUCCESS! 
mysql.server start
Starting MySQL
 SUCCESS!
ログイン後にコピー

フラッシュ中断後はデータベースに再接続できないことがわかります。後続のプログラムは実行できません。

Array
(
    [0] => Array
        (
            [id] => 3
            [name] => terry
        )
)
sleep 10SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
Array
(
)
sleep 10SQLSTATE[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 の値が存在するため、get_conn を呼び出しても再接続は行われませんが、保存された接続が処理に使用されます。

これは実際には、接続が存在する場合、mysql 接続を再度作成して mysql 接続の数を減らす必要がないことを意味します。

したがって、作成されたものの失敗したデータベース接続を使用せずに次回接続を再取得できるように、中断後に self::$_instance の値をクリアする必要があります。

改善方法は以下の通りです。

エラー発生時に呼び出される reset_connect メソッドを追加します。判定エラーが MySQL サーバーが消えました
の場合、既存のデータベース接続はクリアされ、次回から MySQL に再接続されます。 変更された php ファイルは次のとおりです:

db.php


<?php// 数据库操作类class DB{
    // 保存数据库连接
    private static $_instance = null;    // 连接数据库
    public static function get_conn($config){
        if(isset(self::$_instance) && !empty(self::$_instance)){            return self::$_instance;
        }        $dbhost = $config[&#39;host&#39;];        $dbname = $config[&#39;dbname&#39;];        $dbuser = $config[&#39;user&#39;];        $dbpasswd = $config[&#39;password&#39;];        $pconnect = $config[&#39;pconnect&#39;];        $charset = $config[&#39;charset&#39;];        $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; //設置默認編碼
            }            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;
    }    // 执行查询
    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()); // 出错时调用重置连接
        }        $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. フラッシュを再度実行します中断後、現在の実行は失敗しますが、後続の実行は再作成され、新しい接続が継続されることがわかります。

Array(
    [0] => Array
        (
            [id] => 2
            [name] => xfdipzone
        )
)
sleep 10SQLSTATE[HY000]: General error: 2006 MySQL server has gone awayArray(
)
sleep 10Array(
    [0] => Array
        (
            [id] => 1
            [name] => fdipzone
        )
)
sleep 10...
ログイン後にコピー

この記事では、mysql 接続が中断された場合の自動再接続方法に関する関連知識について説明します。さらに関連する内容については、PHP 中国語 Web サイトを参照してください。

関連する推奨事項:

php HTML エンティティ番号と非 ASCII 文字列を

php との間で変換するためのクラス自動インクリメントに応じて、固有の番号クラスが作成されます。

#mysql について現在使用している設定ファイル my.cnf を参照する方法を説明します

以上がmysql接続が中断されたときに自動的に再接続する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート