首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 大結果集查詢記憶體溢出解決方案:PDO 無緩衝查詢詳解

     編輯:PHP 相關知識

問題根源

mysql_query / PDO::query 預設採用緩衝模式:一次性將整個結果集載入 PHP 記憶體。查詢千萬級資料表時,極易觸發 Allowed memory size exhausted 致命錯誤。

解決方案:無緩衝查詢

MySQL 提供 mysql_unbuffered_query,PDO 對應 PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false。特點:

  • 邊查詢邊返回,不佔用大量記憶體。
  • 無法使用 rowCount() 獲取總行數。
  • 同一連線查詢未讀完前,不能執行其他查詢(需關閉游標或新建連線)。

實測對比(表含 1000+ 萬行)

緩衝模式(預設)

function selecttest() {
    $pdo = new PDO("mysql:host=localhost;dbname=test", 'root', '123456');
    // $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); // 註釋=緩衝
    $sth = $pdo->prepare('SELECT * FROM test');
    $sth->execute();
    echo '初始記憶體:' . memory_get_usage() . "\n";
    $i = 0;
    while ($result = $sth->fetch(PDO::FETCH_ASSOC)) {
        $i++; if ($i > 10) break;
        sleep(1);
        print_r($result);
        echo '當前記憶體:' . memory_get_usage() . "\n";
    }
}

結果:執行 $sth->execute() 瞬間記憶體飆升,直接 OOM:

Fatal error: Allowed memory size of 134217728 bytes exhausted
(tried to allocate 204800000 bytes) ... on line 57

無緩衝模式

取消註釋 $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

初始記憶體:144808
Array ( [id] => 1 [a] => v [b] => w [c] => i )
當前記憶體:145544
Array ( [id] => 2 [a] => b [b] => l [c] => q )
當前記憶體:145544
... 記憶體穩定在 145KB 左右,極低且恆定

適用場景與注意事項

場景建議模式
大量資料匯出、ETL、報表生成無緩衝
需要預知總行數、分頁查詢緩衝或另行 COUNT(*)
同一連線交互多條 SQL緩衝或多連線

舊版 mysql_* 函數遷移提示

mysql_unbuffered_query() 在 PHP 5.5+ 棄用,7.0+ 移除。請全面遷移至 PDO 或 mysqli,PDO 範例:

$pdo = new PDO($dsn, $user, $pass, [
    PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false, // 關鍵
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$stmt = $pdo->query('SELECT * FROM huge_table');
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    // 處理單行
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved