php PDO数据库hande在几次成功的调用后拒绝将结果返回给查询

时间:2015-06-01 20:01:52

标签: php sql-server pdo

在我的网站上,我们连接到多个数据库,我们有一个数据库处理类,用于将句柄存储在静态数组中。 99.9%的时间,一切似乎都运行正常,但是偶尔会无声地失败,没有错误,也没有返回任何结果。我已经能够重新创建错误,然后使用以下语法重新创建连接:

$db = new PDO("dblib:host=" . DB_HOST . ";dbname=" . DB_DEFAULT, DB_USER, DB_PASS);

然后,它正确返回结果。但是,我宁愿为所有数据库使用相同的句柄,以保留与创建与数据库的新连接相关的额外开销......或者,至少重新创建连接的次数最少。

无论如何都要评估PDO对象以找出它失败的原因,所以我希望能够弄清楚它是怎么回事?

修改 我已经进一步研究了这个问题,并在发生此错误时对数据库进行了分析。 PDO在遇到某些查询后停止将查询传递给服务器。 (在这种情况下,它是一个插入查询,用于测试记录是否已经存在,如果它没有,那么它会插入它。)

毫无疑问,这对我的问题来说是一个可怕且无法解决的问题,但我复制并粘贴(并通用化了)解决它的问题。基本上,当没有结果返回时,我选择“foo”#39;从数据库中,如果它返回没有结果,我重建连接并尝试再次执行查询。我不接受这个作为答案,因为它非常糟糕。但是这段代码应该更好地说明我试图解决的问题。

/**
 * Executes a line of sql with PDO.
 *
 * @param string $sql
 * @param array $params
 * @param bool
 * @return array
 */
function execute($sql, $params = array(), $retry = false) {
    //this call gets the database handle that is stored in a static array, so we can reuse the same connection
    $db = db::getDB($this->_database);

    if (get_class($db) != 'PDO') {
        error('database handle wasn\'t created succesfully...');
    }

    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);


    try {
        $query = $db->prepare($sql);
        $query->execute($params);
    } catch (Exception $ex) {
        var_dump($ex);
        return false;
    }

    $results = $query->fetchALL(PDO::FETCH_ASSOC);

    if(($retry == false) && (!$results)){
        $newResults = $this->testAndFixResultsIfDBGoneAway($sql, $params);
        if($newResults != false){
            $results = $newResults;
        }
    }

    return $results;
}

function isConnected(){
    $db = db::getDB($this->_database);

    $query = $db->prepare("SELECT 'foo' AS test");
    $query->execute();

    $results = $query->fetchAll(PDO::FETCH_ASSOC);

    //we aren't connected if we get no response
    if($results == array()){
        return false;
    }

    //if there is a response, return true
    return true;
}


function testAndFixResultsIfDBGoneAway($sql, $params){
    if($this->isConnected()){
        return false;
    }

    //recreates the db connection in the db connection class
    db::connect($this->_database);

    $results = $this->execute($sql, $params, true);

    return $results;
}

我注意到我的连接消失了,我可以成功重启,然后下一个查询可能会失败,我可以多次重复这个过程,直到有问题的查询完成,然后一切都开始正常工作,再次。

我真的想知道查询是如何杀死我的数据库连接的,所以我可以阻止它发生,所以我不必在每次都没有返回结果的查询后进行检查。

1 个答案:

答案 0 :(得分:0)

设置PDO错误处理模式以使用异常应该使原因立即明显,这样您就不必四处寻找并使用大量调试代码。

$db = new PDO("dblib:host=" . DB_HOST . ";dbname=" . DB_DEFAULT, DB_USER, DB_PASS, [PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION]);

但是,您必须更新错误处理代码[准备失败,查询失败]以了解异常。