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.
mysqli
PHP 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_RESULT
Khi đã 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->db
nữ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 |