2015-06-01 73 views
2

在我的網站上,我們連接到多個數據庫,並且我們有一個數據庫處理類,它將句柄存儲在一個靜態數組中。 99.9%的時間,一切似乎工作正常,但時不時地處理失敗,沒有錯誤,並沒有結果返回。我已經能夠重新創建錯誤,然後使用以下語法重新創建連接:php PDO數據庫hande拒絕將結果返回給幾個成功調用後的查詢

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

然後,它會正確返回結果。但是,我寧願爲所有數據庫使用相同的句柄,以保留與創建到數據庫的新連接相關的額外開銷......或者至少重新創建連接的次數最少。

有沒有辦法評估PDO對象,找出它失敗的原因,希望能夠弄清楚發生了什麼?

編輯: 我一直在進一步調查,並在發生此錯誤時對DB進行剖析。 PDO在遇到特定查詢後停止向服務器傳遞查詢。 (在這種情況下,它是一個插入查詢,用於測試記錄是否已經存在,如果不存在,則插入它)。

請不要誤解,這是一個可怕的,無法解決的問題,但我複製並粘貼(並普遍化)解決問題的方法。基本上,當沒有結果返回時,我從數據庫中選擇'foo',如果沒有結果,我重建連接並嘗試再次執行查詢。我不接受這個答案,因爲這很糟糕。但是這段代碼應該更好地說明我正在嘗試修復的問題。

/** 
* 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; 
} 

我發現我的連接消失了,我可以成功地重新啓動它,然後下一個查詢可能會失敗,我可以重複此過程多次,直到違規查詢都做了,那麼一切都開始工作通常,再次。

我真的很想知道查詢如何殺死我的數據庫連接,所以我可以阻止它發生,所以我不必在每次查詢都沒有結果後進行檢查。

回答

0

將PDO錯誤處理模式設置爲使用異常應該立即使原因顯而易見,因此您不必四處尋找並使用大量調試代碼。

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

但是,你必須更新你的錯誤處理代碼[準備失敗,失敗的查詢]需要注意的例外。

+0

這是使用設置屬性功能處理的,並且圍繞執行語句進行嘗試......(在我看來,它是SOP)。它在不拋出異常的情況下執行,但對於可以從SSMS中獲得結果的非常簡單的查詢,不會返回任何結果。 –

+0

我唯一能做的其他事情就是[這個bug](https://bugs.php.net/bug.php?id=40639),似乎在8年以後仍然開放... – Sammitch

+0

我已經增加了更多的信息,現在我發現了更多的錯誤。 –