執行 SELECT 查詢後,結果集佔用內存。雖然腳本結束會自動釋放,但長時間運行腳本、大結果集、高併發場景下,主動釋放是良好習慣。
<?php
// 完整示例:查詢 -> 遍歷 -> 釋放 -> 關閉連接
header("Content-Type: text/html; charset=utf-8");
error_reporting(E_ALL & ~E_NOTICE);
$servername = "localhost";
$username = "root";
$password = "admin";
$dbname = "test";
$conn = mysqli_connect($servername, $username, $password, $dbname)
or die("連接失敗: " . mysqli_connect_error());
$sql = "SELECT firstname, lastname, email FROM hello";
$result = mysqli_query($conn, $sql);
if ($result) {
// 遍歷結果集
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
echo "{$row['firstname']} {$row['lastname']} {$row['email']}
";
echo "
";
}
// 關鍵:釋放結果集內存
mysqli_free_result($result);
echo "結果集內存已釋放
";
} else {
die("查詢失敗: " . mysqli_error($conn));
}
// 關閉數據庫連接
mysqli_close($conn);
?>
函數簽名:mysqli_fetch_array(mysqli_result $result, int $resulttype = MYSQLI_BOTH): array|null|false
| 常量 | 返回數組結構 | 訪問方式 | 適用場景 |
|---|---|---|---|
| MYSQLI_ASSOC | 關聯數組 ['field' => 'value'] | $row['field'] | 可讀性最好,推薦日常使用 |
| MYSQLI_NUM | 數字索引數組 [0 => 'value'] | $row[0] | 性能略高,適用大數據量遍歷 |
| MYSQLI_BOTH (默認) | 雙重索引 [0 => 'value', 'field' => 'value'] | 兩種均可 | 兼容舊代碼,內存佔用雙倍 |
// 推薦:明確使用關聯數組
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
// 業務邏輯
}
// 大數據量導出:使用數字索引節省內存
while ($row = mysqli_fetch_array($result, MYSQLI_NUM)) {
fputcsv($fp, $row);
}
$stmt = $conn->prepare("SELECT id, name, email FROM users WHERE status = ? AND created_at > ?");
$stmt->bind_param("is", $status, $date);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
// $row 已按字段名索引
}
$result->free(); // 面向對象風格
$stmt->close();
function processLargeResultSet(mysqli $conn, string $sql, int $batchSize = 1000) {
$offset = 0;
do {
$batchSql = $sql . " LIMIT $offset, $batchSize";
$result = $conn->query($batchSql);
if (!$result) break;
$count = 0;
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
// 處理單行
processRow($row);
$count++;
}
$result->free(); // 及時釋放每批內存
$offset += $batchSize;
} while ($count === $batchSize);
}
| 錯誤現象 | 原因 | 解決方案 |
|---|---|---|
| Call to a member function fetch_array() on boolean | query() 返回 false (SQL 錯誤) | 檢查 $result !== false 後再調用 |
| Commands out of sync | 多語句執行未清理結果集 | 每次查詢後務必 free_result() |
| 內存耗盡 | 大結果集未分批處理 | 使用 LIMIT 分頁或非緩衝查詢 |
| 字段名大小寫不匹配 | MYSQLI_ASSOC 區分大小寫 | SQL 用別名統一大小寫:SELECT name AS user_name |
// 過程風格 $result = mysqli_query($conn, $sql); $row = mysqli_fetch_array($result, MYSQLI_ASSOC); mysqli_free_result($result); // 面向對象風格(推薦) $result = $conn->query($sql); $row = $result->fetch_array(MYSQLI_ASSOC); $result->free(); // mysqli_result 還有更多便利方法 $row = $result->fetch_assoc(); // 等同 MYSQLI_ASSOC $row = $result->fetch_row(); // 等同 MYSQLI_NUM $row = $result->fetch_object(); // 返回對象 $count = $result->num_rows; // 結果集行數 $field = $result->fetch_field(); // 字段元信息
掌握 mysqli 結果集操作細節,能編寫出更健壯、高效、內存友好的數據庫交互代碼,是 PHP 後端開發的核心基本功。