根本原因是存储过程返回多个结果集,而php未显式遍历释放所有结果集,导致连接缓冲区残留数据,触发mysql协议级错误2014;必须用mysqli_multi_query()+next_result()或pdo的nextrowset()循环清理,否则后续操作均会失败。

PHP调用MySQL存储过程时卡住或报错“Commands out of sync”
根本原因是存储过程可能返回多个结果集(比如多个 SELECT 语句),而 PHP 的 MySQLi 或 PDO 默认只消费第一个,后续结果滞留在连接缓冲区里,导致下一次查询失败。这不是代码写错了,是协议层面的约束。
必须显式遍历并释放所有结果集,否则后续任何操作(包括 mysqli_query()、mysqli_close() 甚至脚本结束)都可能异常。
- MySQLi 需配合
mysqli_next_result()+mysqli_use_result()或mysqli_store_result()循环清理 - PDO 则需在每次
execute()后调用nextRowset(),直到返回false - 不释放的结果集会占用连接资源,高并发下容易触发“Too many connections”
MySQLi 方式:用 mysqli_multi_query() 调用并逐个释放
这是最稳妥的方式,尤其适合带输出参数或多个结果集的存储过程。注意不能用 mysqli_query() —— 它不支持多结果协议。
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$mysqli->multi_query("CALL sp_get_user_orders(123)");
do {
if ($result = $mysqli->use_result()) {
while ($row = $result->fetch_assoc()) {
// 处理当前结果集
}
$result->free();
}
} while ($mysqli->next_result());
-
use_result()流式读取,内存友好;store_result()全部缓存到内存,适合小结果集 - 即使某次结果为空(如只有
INSERT无SELECT),use_result()仍会返回null,需判空避免警告 - 忘记
next_result()就等于没释放,整个循环结构缺一不可
PDO 方式:启用 PDO::MYSQL_ATTR_MULTI_STATEMENTS 并手动跳转结果集
PDO 默认禁用多语句,必须在构造时显式开启,否则 CALL 会被截断或报错。
$pdo = new PDO(
'mysql:host=localhost;dbname=db',
'user', 'pass',
[PDO::MYSQL_ATTR_MULTI_STATEMENTS => true]
);
$stmt = $pdo->prepare("CALL sp_get_user_orders(?)");
$stmt->execute([123]);
do {
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 处理当前结果集
} while ($stmt->nextRowset());
-
nextRowset()返回true表示还有下一个结果集,false表示全部释放完毕 - 如果存储过程有
OUT参数,需改用PDO::PARAM_INPUT_OUTPUT绑定变量,不能靠fetchAll()获取 - 若只关心最后一个结果集,仍要调用
nextRowset()跳过前面的,否则连接状态残留
为什么 mysqli_query() 和简单 PDO::query() 不行
它们底层走的是单语句协议路径:mysqli_query() 发送后直接等待单个响应包;PDO::query() 在未开启多语句时,遇到 CALL 中的多个 SELECT 会直接报错 SQLSTATE[HY000]: General error: 2014 Commands out of sync。
- 错误信息里的
2014是 MySQL 官方错误码,专指“客户端未读完上一个结果就发新命令” - 试图用
mysqli_free_result()单独释放无效——它只对上一次query()有效,对multi_query()无意义 - 有些开发者用
mysqli_close()强制断连来“绕过”,但会导致连接池失效、事务中断等更隐蔽问题
SELECT,只要没被显式消费,就会让整个连接进入“半堵塞”状态。不是所有 DBA 都会在 SP 里加注释说明返回几个结果集,得靠实测+释放逻辑兜底。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











