🧠 1️⃣ Mặc định: mysqli luôn buffered

Khi bạn chạy:

$result = $mysqli->query("SELECT * FROM big_table");

thì mặc định mysqli sẽ:

  • Đọc toàn bộ dữ liệu từ MySQL về RAM PHP ngay lập tức.
  • Kể cả khi bạn chưa fetch_assoc() dòng nào.
  • Giống hệt PDO::MYSQL_ATTR_USE_BUFFERED_QUERY = true.

🧩 Nghĩa là: nếu bạn SELECT * chứa BLOB, toàn bộ BLOB đều nằm trong RAM rồi.


⚙️ 2️⃣ Cách duy nhất để “tắt buffer” trong 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);

Ví dụ:

$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.

🚫 3️⃣ Giới hạn của 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ăngHỗ 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.


🧩 4️⃣ Trong CodeIgniter 3

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.

Nếu bạn muốn unbuffered trong CI3:

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')).

💡 5️⃣ Gợi ý thực tế

Nhu cầuGiả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

✅ Tóm tắt nhanh

DriverBuffered mặc địnhCó thể tắt khôngCá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