在使用PHP 操作MySQL 數據庫時,如果你採用了mysqli擴展進行多語句查詢(multi-query),你很可能會遇到next_result()方法。而很多人忽視了一個重要細節——。
本文將帶你了解這個問題的成因、表現以及如何避免。
當你通過mysqli::multi_query()執行多條SQL 時,MySQL 會返回多個結果集。通過mysqli::next_result()可以逐個訪問這些結果集,配合mysqli::store_result()來獲取每一個結果的內容。
$mysqli = new mysqli("localhost", "user", "password", "database");
$sql = "SELECT * FROM users; SELECT * FROM orders;";
if ($mysqli->multi_query($sql)) {
do {
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_assoc()) {
// 處理每一行數據
echo $row["id"] . "<br>";
}
// 釋放結果集
$result->free();
}
} while ($mysqli->next_result());
}
在這個例子中,每次通過store_result()獲取一個結果集,並用完後通過$result->free()釋放它。
如果你省略了$result->free() ,如下所示:
// ? 未釋放結果集的代码示例
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_assoc()) {
echo $row["id"] . "<br>";
}
// 忽略了 $result->free();
}
那麼你程序中的內存佔用就會持續增長,尤其在處理大量數據或高並發請求時,這種內存洩漏會非常明顯。因為mysqli擴展會將結果集緩存在客戶端內存中,只有顯式釋放它,PHP 才能回收這些資源。
程序長時間運行後內存暴漲;
服務器響應變慢甚至崩潰;
PHP 報出Allowed memory size exhausted錯誤;
無法追踪的性能問題。
這在高流量的API、定時任務或者守護進程中尤為致命。
總是記得在處理完結果集後調用$result->free() 。此外,也要在next_result()每次調用之後檢查是否還有新的結果集並處理它們。
$mysqli = new mysqli("localhost", "user", "password", "database");
$sql = "CALL complex_procedure(); CALL another_procedure();";
if ($mysqli->multi_query($sql)) {
do {
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_assoc()) {
// 處理每一行
}
$result->free(); // ? 正確釋放
}
} while ($mysqli->more_results() && $mysqli->next_result());
}
使用memory_get_usage()或xdebug工具監控內存使用;
使用Linux 命令如top或htop監控進程內存;
日誌記錄每次查詢後的內存使用。
使用mysqli::next_result()時不釋放結果集,確實會導致PHP 腳本內存洩漏。正確的做法是每次處理完結果集之後都調用$result->free() 。這不僅能保持程序健壯,還能避免因內存佔用過高導致的性能問題。
如果你在構建複雜的數據接口或批量處理數據的服務,尤其要注意這一點。
更多關於mysqli多結果集處理的官方文檔,可以訪問:
https://gitbox.net/docs/php/mysqli-multi-query (假設的鏈接)
希望這篇文章能幫你避開PHP 開發中的常見坑。