我正在尝试使用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。
在花费大量时间尝试隔离我的代码部分来解决此问题之后,我注意到将ATTR_EMULATE_PREPARES标志设置为true后,错误消失了。
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
这告诉PDO模仿准备好的语句,而不是MySQL本身。根据我的阅读,如果您使用的是MySQL和PHP的最新版本,通常建议关闭此标志(默认情况下为true)。
我确实相信这是MySQL的错误(我在5.6.17版之前有问题)。关于此特定问题的讨论不多,因此希望这可以节省其他人的故障排除时间。这个MySQL Bug页面上也讨论了这个问题,但是发布的解决方案对我的情况没有帮助。