一尘不染

调用MySQL存储过程时数据包出现乱序错误

sql

我正在尝试使用PDO调用存储的proc,但是在尝试对结果进行获取时出现以下错误。

警告:数据包乱序。 预期收到1个。16数据包大小= 163

我存储的proc使用的是我从临时表中选择之前关闭的两个游标。我怀疑这可能是问题所在,因为我可以直接在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块中有此代码,没有异常被抛出。实际上,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。


阅读 136

收藏
2021-03-17

共1个答案

一尘不染

在花费大量时间尝试隔离我的代码部分来解决此问题之后,我注意到将ATTR_EMULATE_PREPARES标志设置为true后,错误消失了。

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

这告诉PDO模仿准备好的语句,而不是MySQL本身。根据我的阅读,如果您使用的是MySQL和PHP的最新版本,通常建议关闭此标志(默认情况下为true)。

我确实相信这是MySQL的错误(我在5.6.17版之前有问题)。关于此特定问题的讨论不多,因此希望这可以节省其他人的故障排除时间。这个MySQL
Bug页面
上也讨论了这个问题,但是发布的解决方案对我的情况没有帮助。

2021-03-17