pdo::mysql_attr_use_buffered_query 控制查询结果是否在php端一次性缓存:设为true则全量加载,false则流式逐行拉取;必须在new pdo()时初始化,且需同时关闭pdo::attr_emulate_prepares,否则失效。

PHP 中 PDO 的 PDO::MYSQL_ATTR_USE_BUFFERED_QUERY 控制的是查询结果是否在 PHP 端一次性缓存——开则全量加载,关则流式逐行拉取。它不是“游标开关”,而是缓冲行为的总开关,直接影响内存占用、响应延迟和连接复用能力。
缓冲模式(true):默认行为,适合小结果集
开启时,PDO 在 execute() 或 query() 后立刻从 MySQL 服务端拉取全部数据,存入 PHP 内存,再供 fetch() 遍历。此时:
- 可反复调用
fetch()、fetchAll()、rowCount(),甚至seek()回退指针 - 同一连接可并发执行其他查询(比如边读用户表边插入日志)
- 但 100 万行数据可能占数 GB 内存,容易触发
Allowed memory size exhausted - 对大数据导出、实时报表等场景不友好
非缓冲模式(false):流式处理,适合大结果集
关闭后,PDO 不预取全部结果,每次 fetch() 才向 MySQL 请求下一行(网络 I/O 块等待)。关键点:
- 必须在
new PDO()时传入,不能用setAttribute()动态修改 - 必须同时设
PDO::ATTR_EMULATE_PREPARES => false,否则模拟预处理会强制缓冲,开关失效 - 结果集不可回溯,
rowCount()返回 -1,seek()报错 - 同一连接在结果未读完前不能再发新查询,否则报
Commands out of sync
常见误用与修复写法
很多人写了 $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false) 却没生效,就是因为属性必须初始化时设定。正确连接示例:
$pdo = new PDO($dsn, $user, $pass, [
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
之后用 while ($row = $stmt->fetch()) { echo json_encode($row); flush(); } 就能实现边查边输出,避免等待全部完成。
和 MySQLi 的对应关系
MySQLi 默认就是非缓冲(use_result),相当于 PDO 关闭缓冲后的行为;若想在 MySQLi 中启用缓冲,需显式调用 mysqli_store_result() 或使用 mysqli_query($conn, $sql, MYSQLI_STORE_RESULT)。两者逻辑对称,但 PDO 的配置更集中,MySQLi 更分散。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











