mysqli luôn bufferedKhi bạn chạy:
$result = $mysqli->query("SELECT * FROM big_table");
thì mặc định mysqli sẽ:
fetch_assoc() dòng nào.PDO::MYSQL_ATTR_USE_BUFFERED_QUERY = true.🧩 Nghĩa là: nếu bạn
SELECT *chứaBLOB, toàn bộ BLOB đều nằm trong RAM rồi.
mysqliPHP cung cấp một hàm khác biệt để truy vấn không buffer:
mysqli_real_query() + mysqli_use_result()
hoặc rút gọn hơn:
$result = $mysqli->query("SELECT * FROM big_table", MYSQLI_USE_RESULT);
$mysqli = new mysqli("localhost", "root", "", "test");
// 🚫 Unbuffered query
$result = $mysqli->query("SELECT * FROM tbl_blob", MYSQLI_USE_RESULT);
while ($row = $result->fetch_assoc()) {
process($row);
}
$result->close();
📌 Ở đây:
MYSQLI_USE_RESULT = tương đương PDO::MYSQL_ATTR_USE_BUFFERED_QUERY = false.MYSQLI_STORE_RESULT (mặc định) = tương đương true.MYSQLI_USE_RESULTKhi đã bật unbuffered query bằng MYSQLI_USE_RESULT, có một số giới hạn quan trọng:
| Tính năng | Hỗ trợ |
|---|---|
| Chạy query khác trong khi chưa đọc hết dữ liệu | ❌ Không |
Dùng num_rows | ❌ Không |
Dùng data_seek() | ❌ Không |
| Đọc song song nhiều query | ❌ Không |
Giải phóng bộ nhớ sớm ($result->close()) | ✅ Bắt buộc sau khi đọc xong |
Vì MySQL chỉ gửi từng dòng qua socket, nên connection bị "chiếm" cho tới khi bạn đọc hết.
CI3 khi dùng dbdriver = 'mysqli', nó gọi nội bộ:
$result = mysqli_query($this->conn_id, $sql);
→ tức là luôn buffered (MYSQLI_STORE_RESULT).
CI3 không có cấu hình để chuyển sang MYSQLI_USE_RESULT.
Bạn phải tự sửa core nếu muốn.
Sửa file:
/system/database/drivers/mysqli/mysqli_driver.php
Tìm dòng:
$result = @mysqli_query($this->conn_id, $sql);
Thay bằng:
$result = @mysqli_query($this->conn_id, $sql, MYSQLI_USE_RESULT);
⚠️ Lưu ý:
- Cách này ảnh hưởng toàn bộ hệ thống, nên chỉ dùng khi chắc chắn bạn chỉ fetch tuần tự.
- Không thể chạy 2 query song song qua
$this->dbnữa.- Không dùng
result_array()(nó cố load toàn bộ data, sẽ lỗi).- Phải fetch thủ công bằng
while ($row = $query->unbuffered_row('array')).
| Nhu cầu | Giải pháp |
|---|---|
| Muốn dùng CI3, ít sửa code | → Dùng pdo driver và tắt buffer |
Muốn tối ưu RAM, nhưng vẫn mysqli | → Sửa core: thêm MYSQLI_USE_RESULT |
| Chỉ cần PHP thuần | → Dùng mysqli_query($sql, MYSQLI_USE_RESULT) |
| Dữ liệu nhỏ, tốc độ > RAM | → Giữ nguyên mặc định |
| Driver | Buffered mặc định | Có thể tắt không | Cách tắt |
|---|---|---|---|
PDO | ✅ Có | ✅ PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false | |
mysqli | ✅ Có | ⚙️ Thủ công MYSQLI_USE_RESULT | |
CI3 pdo | ✅ Có | ✅ Qua $db['options'] | |
CI3 mysqli | ✅ Có | ⚙️ Phải sửa core |