我正在尝试使用 PDO 调用存储过程,但在尝试获取结果时出现以下错误。
警告:数据包乱序。预期 1 收到 16. Packet size=163
我的存储过程使用了两个游标,我在从临时表中选择之前关闭了这两个游标。我怀疑这可能是问题所在,因为我可以直接在 MySQL 中调用我的 SP 并可以看到结果。在迁移到 php_pdo_mysql.dll 之前使用 php_mysql 扩展时,我也从来没有遇到过这个 SP 的问题。 我还可以使用 PDO 在 PHP 中调用包含 INPUT 参数的其他更简单的存储过程,并且可以毫无错误地获取结果。
这是返回错误的代码:
$db = new PDO('mysql:host='.__DB_HOST__.';dbname='.__DB_NAME__.';charset=utf8', __DB_USER__, __DB_PASS__);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
/* DOES NOT WORK */
$queryResult = $db->prepare("CALL GetResults(:siteId,null)");
$siteId = 19;
$queryResult->bindValue(':siteId', $siteId, PDO::PARAM_INT);
$queryResult->execute();
$result = $queryResult->fetchAll(PDO::FETCH_ASSOC); // returns packets out of order warning
print_r($result);
我在 Try/Catch block 中有这段代码,没有抛出异常。事实上,PHP 在浏览器中将此显示为警告。
我的存储过程签名如下所示:
CREATE DEFINER=`root`@`localhost`
PROCEDURE `GetResults`(IN siteIdParam INT(11), IN siteSearchText VARCHAR(45))
我也不确定问题是否在于将 null 作为参数之一传递。有时第一个参数传递 null,有时是第二个。但无论如何它总是直接在 MySQL 服务器上运行。
我尝试了 bindParam 和 bindValue,结果相同。我也可以发布我的 SP,但这可能有点矫枉过正。
有什么方法可以从 PDO 扩展打开额外的日志记录吗?
有什么想法或建议吗?如果您需要更多信息,请告诉我。
注意:我使用的是 PHP v5.5.4 和 MySQL v5.6.14。
最佳答案
在花了很多时间尝试隔离部分代码来解决这个问题后,我注意到在将 ATTR_EMULATE_PREPARES 标志设置为 true 后错误消失了。
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
这告诉 PDO 模拟准备好的语句,而不是 MySQL 本地模拟。根据我的阅读,如果您使用的是最新版本的 MySQL 和 PHP,通常建议关闭此标志(默认情况下为真)。您可以在此 SO article 中找到更多相关信息.
我相信这是 MySQL 的一个错误(我在 5.6.17 版本之前遇到过这个问题)。关于这个特定问题的讨论不多,所以希望这可以节省其他人的故障排除时间。该问题也在 this MySQL bug page 上进行了讨论。 ,但发布的解决方案对我的情况没有帮助。
关于php - 调用 MySQL 存储过程时数据包乱序错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19389809/