升级LAMP后mysqli同步错误修复:db_query与db_fetch改写
解决mysqli "Commands out of sync" 错误的db_query/db_fetch函数改写方案
这个错误本质是数据库连接上存在未完全处理的残留结果集,新版mysqli启用严格模式后触发了该异常。以下是保留stmt_init/prepare/execute/store_result核心流程的改写方案,完全适配原有代码调用逻辑:
改写后的db_query函数
function db_query($q, $params = []) { global $mysqli; // 替换为你的全局mysqli连接变量 // 核心修复:清理连接中未处理的残留结果集 while ($mysqli->more_results()) { $mysqli->next_result(); if ($res = $mysqli->store_result()) { $res->free(); } } $stmt = $mysqli->stmt_init(); if (!$stmt->prepare($q)) { trigger_error("SQL Prepare失败: " . $stmt->error, E_USER_ERROR); return false; } // 适配原有参数绑定逻辑(如果你的代码有自定义类型,可修改$types生成规则) if (!empty($params)) { $types = str_repeat('s', count($params)); // s=字符串,i=整数,d=浮点数,b=二进制 $stmt->bind_param($types, ...$params); } if (!$stmt->execute()) { trigger_error("SQL Execute失败: " . $stmt->error, E_USER_ERROR); $stmt->close(); return false; } // 保留store_result核心流程,兼容无结果的查询(如INSERT/UPDATE) if (!$stmt->store_result() && $stmt->errno !== 0) { trigger_error("Store Result失败: " . $stmt->error, E_USER_ERROR); $stmt->close(); return false; } return $stmt; }
改写后的db_fetch函数
function db_fetch($stmt) { if (!$stmt || $stmt->num_rows === 0) { $stmt->close(); return false; } // 自动绑定结果字段,适配原有关联数组返回格式 $meta = $stmt->result_metadata(); $fields = []; $bindVars = []; while ($field = $meta->fetch_field()) { $fields[] = &$bindVars[$field->name]; } call_user_func_array([$stmt, 'bind_result'], $fields); $meta->free(); // 读取单行结果 if ($stmt->fetch()) { $result = []; foreach ($bindVars as $key => $val) { $result[$key] = $val; } return $result; } else { // 结果读取完毕,释放资源避免残留 $stmt->free_result(); $stmt->close(); return false; } }
关键修复点说明
- 残留结果集清理:db_query开头的循环强制清空连接中所有未处理的结果集,从根源解决命令不同步问题
- 资源自动释放:db_fetch在结果读取完毕后主动调用
free_result()和close(),避免资源残留 - 兼容原有逻辑:完全保留核心流程,原有代码中
$stmt = db_query($sql); while ($row = db_fetch($stmt)) {}的调用方式无需修改 - 无结果查询兼容:处理了INSERT/UPDATE等无需返回结果的场景,避免store_result报错
内容的提问来源于stack exchange,提问作者cricketplayer123
相关产品推荐
相关产品推荐

