PDO:MySQL服务器已经消失,无法捕获异常

时间:2018-10-07 02:46:11

标签: php mysql pdo

概述
我正在使用websockets(Ratchet)聊天系统。聊天工作正常,但是我的数据库类遇到了一些问题。

问题
在开发过程中,聊天系统显然没有被大量访问。这将导致MySQL服务器最终关闭连接。为了解决该问题,我编写了一些异常处理程序以重新连接到MySQL服务器。但是,这不起作用。这是我的代码外观的最低限度:

<?php

Class Database {
    private $host = DB_HOST;
    private $user = DB_USER;
    private $pass = DB_PASS;
    private $dbname = DB_NAME;

    private $dbh;
    private $error;

    private $stmt;

    public function __construct(){

        if($this->dbh === null){
            $this->reconnect();
        }
    }

    private function reconnect(){
        // Set DSN
        $dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
        // Set options
        $options = array(
            PDO::ATTR_PERSISTENT    => false,
            PDO::ATTR_ERRMODE       => PDO::ERRMODE_EXCEPTION
        );
        // Create a new PDO instanace
        try{
            $this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
        }
        // Catch any errors
        catch(PDOException $e){
            $this->error = $e->getMessage();
            return $this->error;
        }
    }

    /* Execute query */
    public function execute(){
        try{
            return $this->stmt->execute();
        }
        catch(PDOException $e){
            $this->reconnect();

            try{
                return $this->stmt->execute();
            }
            catch(PDOException $e){
                $this->error = $e->getMessage();
                return $this->error;
            }
        }
    }

当然还有更多的模拟方法,但是这些方法并不重要。

出现的错误如下:

  

PHP致命错误:未捕获的PDOException:SQLSTATE [HY000]:常规错误:2006 MySQL服务器已不在/var/www/clients/client1/web4/web/src/Pdo.php:43中   堆栈跟踪:
  /var/www/clients/client1/web4/web/src/Pdo.php(43):PDOStatement-> execute()

该错误指向上面的return $this->stmt->execute();方法中的execute()

  1. 当我清楚地发现它时,错误怎么可能告诉我“未捕获的PDOException”
  2. 当我不使用持久连接时,MySQL服务器如何断开连接? PDO::ATTR_PERSISTENT => false,

1 个答案:

答案 0 :(得分:3)

根据注释中的确定,您正在另一个命名空间中运行此代码。这意味着catch (PDOException $e)实际上是catch (\Your\Namespace\PDOException $e),所以将不起作用。您要么需要在类前面加一个反斜杠作为前缀,然后将其放入全局名称空间中:

catch(\PDOException $e){
    $this->error = $e->getMessage();
    return $this->error;
}

或在代码开头use这个类。

use \PDOException;