2013-01-23 35 views
4

我目前正在開發一個使用PDO的PHP應用程序。我正在寫一個導入,它讀入一個CSV文件,檢查數據庫中的記錄,以及更新,刪除等等......PHP 5.3.5 PDO FETCH_OBJ內存泄漏?

我注意到的東西是這個腳本使用的內存似乎很高,它似乎可以做我的執行查詢的方式。參閱下面的是用於在CSV每一行執行的示例性查詢:

$qry = "SELECT * FROM company WHERE id = 1"; 
$sth = $this->prepare($qry); 
$sth->execute(); 
$sth->setFetchMode(PDO::FETCH_INTO, new Company()); 
$sth->fetch(); 

對於上述memory_get_peak_usage()= 6291456

當使用以下:

$qry = "SELECT * FROM company WHERE id = 1"; 
$sth = $this->prepare($qry); 
$sth->execute(); 
$sth->setFetchMode(PDO::FETCH_CLASS, "Company"); 
$sth->fetch(); 

用於上述memory_get_peak_usage ()= 524288

正如你所看到的差異是相當大的。

我想我已經3個問題..

  1. 是否有使用PDO :: FETCH_OBJ時內存泄漏在PHP 5.3.5?
  2. 使用FETCH_CLASS而不是FETCH_OBJ有什麼區別嗎?
  3. 有沒有其他人遇到同樣的問題?

公司類很簡單:

class Company { 
    function __construct(){} 
    /**classvars**/ 
    public $_tablename = 'company'; 
    public $transient; 
    public $id; 
    public $name; 
    /**endclassvars**/ 
} 
+0

@MikeB:但他所問的問題是爲什麼激烈的差異。 –

+0

@Martin你有理由誤解了'PDO :: FETCH_OBJ'。查看我的回答 – hek2mgl

+0

@MikeB公司類的內容與它無關......他以任何方式實例化公司對象。公司班級*做什麼都沒有關係,因爲它們在兩種情況下都做同樣的事情。 – meagar

回答

2

注意:原來的答案被賦予前的OP改變PDO::FETCH_OBJPDO::FETCH_INTO

該更新我試着用重現行爲後PHP 5.3.10-1ubuntu3.4。在兩種獲取模式之間,內存消耗沒有顯着差異。我已經使用大型MySQL表和大型SQLite數據庫進行了測試。

由於@SDC提到該錯誤是已知的,並且在5.3.5之後被修復。 (至少在我見過的5.3.10中)。

結論:您必須升級您的PHP版本。


雖然行爲很有趣,應該調查,但您使用PDO::setFetchMode()的方式不正確。當$模式 - 第一個參數 - 是PDO :: FETCH_OBJ 第二個參數是預期的。如果使用第二個參數,則對setFetchMode()的調用將失敗(返回false),並使用默認獲取模式FETCH_BOTH

使PDO::ERRMODE_EXCEPTION時,你可以看到這個錯誤:

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

$stmt = $db->query('....'); 

// the following line will trigger an exception 
$stmt->setFetchMode(PDO::FETCH_OBJ, new Company()); 

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: fetch mode doesn't allow any extra arguments'

當你期望的是結果行應在特定的類的對象,然後PDO::FETCH_CLASS是工作的嘗試。PDO::FETCH_OBJ將從型StdClass

+0

對不起,我已經把錯誤的代碼..它不是PDO :: FETCH_OBJ,我有什麼是PDO :: FETCH_INTO。問題依然存在。我編輯了我的帖子 – Martin

+0

@Martin好的,會進一步調查。當前瀏覽pdo_stmt.c :) – hek2mgl

0

FETCH_INTO返回對象:手段獲取到現有的對象(即用新如創建)

FETCH_CLASS:指取到一個新的對象(構造函數被調用每行)

要小心,如果公司類中的構造函數具有依賴關係,則會爲每一行調用它們。因此,構造函數不應該包含執行數據庫連接的函數或類,例如只有簡單的初始化...

你的公司類是怎麼樣的?

+0

看到 – Martin

+0

類編輯好後認爲,差異來自行:$ sth->調用setFetchMode(PDO :: FETCH_INTO,新的公司());如果你正在調用$ sth-> setFetchMode(PDO :: FETCH_CLASS,「Company」); PHP必須確定並創建這個類,在第一種情況下,它還好。 –

3

看着PHP changelog,似乎在5.3.4中有一個相關的修復,其中一個memory leak was fixed in PDO FETCH_INTO

從你說的話,我懷疑是的,這是你看到的錯誤。當然,解決方案是升級 - 在舊的補丁版本中堅持不懈是沒有意義的。

即使這不是你所看到的錯誤,在5.3.3和現在版本之間的版本中有很多的PDO修復;我相信至少有一些與你有關的機會很大。

+0

謝謝指出。在我發佈的版本中猜測它只是FETCH_INTO。我將不得不嘗試升級並檢查出來。再次感謝 – Martin