簡體   English   中英

PHP PDO fetch() 循環在處理部分大型數據集后終止

[英]PHP PDO fetch() loop dies after processing part of large dataset

我有一個 PHP 腳本,它在一個典型的循環中將來自 PDO 查詢的“大”數據集(大約 10 萬條記錄)處理為單個對象集合:

while ($record = $query->fetch()) {
    $obj = new Thing($record);

    /* do some processing */

    $list[] = $obj;
    $count++;
}

error_log('Processed '.$count.' records');

這個循環處理了大約 50% 的數據集,然后莫名其妙地中斷了。

我嘗試過的事情:

  • 內存分析: memory_get_peak_usage()在循環終止之前始終輸出大約 63MB。 內存限制為 512MB,通過 php.ini 設置。
  • 使用set_time_limit()將腳本執行時間增加到 1 小時(3600 秒)。 循環在那之前很久就中斷了,我在日志中沒有看到這個錯誤的常見錯誤。
  • PDO::MYSQL_ATTR_USE_BUFFERED_QUERY設置為false以避免緩沖整個數據集
  • 在循環中斷后立即注銷$query->errorInfo() 這沒有幫助,因為錯誤代碼是“00000”。
  • 檢查 MySQL 錯誤日志。 在此腳本運行之前、之后或期間,沒有任何值得注意的地方。
  • 將處理分批處理為 20K 記錄塊。 沒有不同。 循環在同一地點破裂。 但是,通過在每批結束時“清理”PDO 語句對象,我能夠將處理的總數提高到 54%。

其他奇怪的行為:

  • 當我使用ini_set('memory_limit', '1024MB')設置內存限制時,循環實際上比使用較小的內存限制更早結束,進度約為 20%。
  • 在這個循環中,PHP 進程使用了​​ 100% 的 CPU,但是一旦它中斷,使用率就會下降到 2%,盡管隨后立即在另一個循環中進行了處理。 很可能,在第一個循環中與 MySQL 服務器的連接非常耗費資源。

如果這有什么不同,我將使用 MAMP PRO 在本地完成所有這些操作。

有沒有其他東西可以持續打破我沒有檢查過的這個循環? 這難道不是處理這么多記錄的可行策略嗎?

更新

使用批處理策略(以 20K 為增量)后,我開始在第三批MySQL server has gone away始終看到 MySQL 錯誤: MySQL server has gone away 可能是長時間運行的無緩沖查詢的症狀。

如果您真的需要動態處理 100K 條記錄,您應該在 SQL 中進行處理,並根據需要獲取結果 - 這應該可以節省大量時間。

但是由於某種原因,您可能無法這樣做。 你總是處理語句中的所有行,所以使用 fetchAll 一次 - 然后讓 MySQL 單獨使用,就像這樣:

$records = $query->fetchAll()
foreach ($records as record) 
{
    $obj = new Thing($record);
    /* do some processing */
    $list[] = $obj;
    $count++;
}
error_log('Processed '.$count.' records');

此外,僅選擇您將使用的行。 如果這沒有幫助,您可以嘗試這樣做: 使用 PDO 設置連接超時

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM