關於數據庫斷線重連的一點點思考

最近在寫數據庫連接池,一個不可逃避的問題就是數據庫斷線重連。 查了不少資料,由於公司有不少項目用了 TP5 因而也去看了它的源碼。php

tp5的實現其實很簡單,配置了一些數據庫鏈接相關的錯誤信息關鍵詞(句),而後在執行語句時 catch 異常信息進行比對:mysql

// 服務器斷線標識字符
    protected $breakMatchStr = [
        'server has gone away',
        'no connection to the server',
        'Lost connection',
        'is dead or not enabled',
        'Error while sending',
        'decryption failed or bad record mac',
        'server closed the connection unexpectedly',
        'SSL connection has been closed unexpectedly',
        'Error writing data to the connection',
        'Resource deadlock avoided',
        'failed with errno',
    ];
catch (\PDOException $e) {
            if ($this->isBreak($e)) {
                return $this->close()->query($sql, $bind, $master, $pdo);
            }
            throw new PDOException($e, $this->config, $this->getLastsql());
        }
protected function isBreak($e): bool
    {
        if (!$this->config['break_reconnect']) {
            return false;
        }
        $error = $e->getMessage();
        foreach ($this->breakMatchStr as $msg) {
            if (false !== stripos($error, $msg)) {
                return true;
            }
        }
        return false;
    }

(噢 忽然發現5.2已經開始使用 php7新特性了)sql

感受用 errMessage 沒有 errCode 靠譜吧,可是用 errCode 也很頭疼啊,我要蒐集各類數據庫的鏈接相關的錯誤碼,tp5自帶的那些錯誤信息也只是 mysql 的吧,至少沒看見sqlserver 的「TCP Provider: Error code 0x2746」,個人鏈接池是想支持多種數據庫的。。。數據庫

正在頭疼的時候,忽然靈光一現:服務器

從鏈接池取出db鏈接對象時,先執行一句相似「select 1」這樣的很是簡單、不會有語法錯誤、與業務無關(表無關、字段無關。。。) 的語句,若是報錯則理論上證實即便不是鏈接問題 它也已經不能正常執行業務SQL了,再加一個重連次數限制,防止特殊狀況下有可能發生的死循環。。。應該就完美了。。。php7

/**
     * 檢查 db鏈接對象 是否可用, 主要針對斷線重連
     * @param $dbKey
     * @return bool
     */
    static private function _check($dbKey)
    {
        try {
            self::$dbUsing[$dbKey]->check();
        } catch (\Exception $e) {
            return false;
        }
        return true;
    }
function check(){
        $this->prepare('select 1');
        return $this->execute();
    }

還有一種思路是作「心跳」檢查,定時把鏈接池裏的對象「請」出來「遛」一下,使其保持「活力」。。。可是這個和斷線重連並不衝突,能夠疊加使用,效果更好。。。ide


另:在測試中發現,mysql 好像能夠自動重連具體表現爲:在一個斷開的 pdo鏈接對象執行第一句sql 時 catch 了異常並讓代碼繼續執行,則後面的 sql 就能夠執行成功。sqlserver

我在網上沒有查到這一行爲相關資料,因此不肯定它與 pdo 有關或是 mysql 的功能 又是否跟mysql版本有關。。。測試

相關文章
相關標籤/搜索