Php 调用MySQL存储过程时出现数据包无序错误
我试图使用PDO调用一个存储的proc,但在尝试获取结果时出现以下错误 警告:数据包顺序错误。预期1人收到16份。数据包大小=163 我的存储过程使用两个游标,在从临时表中选择之前关闭它们。我怀疑这可能是问题所在,因为我可以在MySQL中直接调用我的SP,并且可以看到结果。在迁移到php_pdo_mysql.dll之前,使用php_mysql扩展时,我也从未遇到过这个SP的问题。 我还可以使用PDO在PHP中调用包含输入参数的其他更简单的存储过程,并且可以获取结果而不会出现任何错误 以下是返回错误的代码:Php 调用MySQL存储过程时出现数据包无序错误,php,mysql,sql,stored-procedures,pdo,Php,Mysql,Sql,Stored Procedures,Pdo,我试图使用PDO调用一个存储的proc,但在尝试获取结果时出现以下错误 警告:数据包顺序错误。预期1人收到16份。数据包大小=163 我的存储过程使用两个游标,在从临时表中选择之前关闭它们。我怀疑这可能是问题所在,因为我可以在MySQL中直接调用我的SP,并且可以看到结果。在迁移到php_pdo_mysql.dll之前,使用php_mysql扩展时,我也从未遇到过这个SP的问题。 我还可以使用PDO在PHP中调用包含输入参数的其他更简单的存储过程,并且可以获取结果而不会出现任何错误 以下是返回错
$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))
$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); // works fine
print_r($result);
// Call a second stored procedure
$secondCall = $db->prepare("CALL GetOtherResults()");
$secondCall->execute();
$secondResult = $secondCall->fetchAll(PDO::FETCH_ASSOC); // returns packets out of order
print_r($secondResult);
我也不确定问题是否在于将null作为参数之一传递。有时第一个参数传递null,有时是第二个。但无论如何,它总是直接在MySQL服务器上工作
我尝试了bindParam和bindValue,结果相同。我也可以发布我的SP,但这可能有点过头了
有没有办法从PDO扩展打开其他日志记录
有什么想法或建议吗?如果你需要更多的信息,请告诉我
注意:我使用的是PHP v5.5.4和MySQL v5.6.14。在花了很多时间试图隔离部分代码以解决此问题后,我注意到在将ATTR\u EMULATE\u PREPARES标志设置为true后,错误消失了
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
这告诉PDO模拟准备好的语句,而不是通过MySQL本机模拟。从我所读到的内容来看,如果您使用的是最新版本的MySQL和PHP,通常建议您关闭此标志(默认情况下为true)。你可以在这里找到更多的信息
我确信这是MySQL的一个bug(我在5.6.17版本之前就遇到了这个问题)。关于这个问题没有太多的讨论,所以希望这可以为其他人节省数小时的故障排除时间。上也讨论了这个问题,但发布的解决方案对我的情况没有帮助。@http203我在使用WAMP server和mysql 5.6.17时遇到了同样的问题
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
修复了这个问题,但我也建议增加mysql.ini中的查询限制
max_allowed_packet = 1MB //Default
到
为了防止将来出现问题,对于任何有相关问题的人,请阅读这篇参考文章我在尝试更改PDO::ATTR_EMULATE_属性时遇到了相同的问题 当我尝试在同一PDO连接上调用第二条准备好的语句时,我可以可靠地重现您描述的内容。大概是这样的:
CREATE DEFINER=`root`@`localhost`
PROCEDURE `GetResults`(IN siteIdParam INT(11), IN siteSearchText VARCHAR(45))
$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); // works fine
print_r($result);
// Call a second stored procedure
$secondCall = $db->prepare("CALL GetOtherResults()");
$secondCall->execute();
$secondResult = $secondCall->fetchAll(PDO::FETCH_ASSOC); // returns packets out of order
print_r($secondResult);
我知道您的示例只显示了一个调用,但要触发此错误,存储的proc调用不必位于同一个文件中,只需共享同一个PDO连接即可。我希望下面的建议仍然有用
执行存储过程时,MySQL驱动程序返回两个行集。本机驱动程序要求您在重新使用连接之前处理两者。你需要,即使你不在乎里面有什么,也要在准备和打第二个电话之前。像这样:
...
$queryResult->execute();
$result = $queryResult->fetchAll(PDO::FETCH_ASSOC);
$queryResult->nextRowSet();
$queryResult->closeCursor();
// Now you can prepare your second statement
...
如果你忘了打这两个额外的电话,PDO的模拟准备会更宽容 对于我来说,将
PDO::ATTR_PERSISTENT
设置为false
解决了这个问题
问题在升级mysql之后开始出现。不确定实际问题是什么:-/ 我的存储过程中有游标。我通过一次获取所有记录,然后遍历来解决这个问题。我再也没有这个“通知”了
$sqlQuery = $conn->prepare('CALL myStoredProcedure(?,?)');
$sqlQuery->bind_param('ss', $param1, $param2);
$sqlQuery->execute();
$resultSet = $sqlQuery->get_result();
$result = $resultSet->fetch_all();
$len = sizeof($result);
for($i=0; $i < $len; $i++){
// Fetching data and processing it
}
$sqlQuery=$conn->prepare('callmystoredprocesdure(?,));
$sqlQuery->bind_param('ss',$param1,$param2);
$sqlQuery->execute();
$resultSet=$sqlQuery->get_result();
$result=$resultSet->fetch_all();
$len=sizeof($result);
对于($i=0;$i<$len;$i++){
//获取数据并对其进行处理
}
在我的情况下,我需要关闭数据库连接
我的错误如下所示:
CREATE DEFINER=`root`@`localhost`
PROCEDURE `GetResults`(IN siteIdParam INT(11), IN siteSearchText VARCHAR(45))
$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); // works fine
print_r($result);
// Call a second stored procedure
$secondCall = $db->prepare("CALL GetOtherResults()");
$secondCall->execute();
$secondResult = $secondCall->fetchAll(PDO::FETCH_ASSOC); // returns packets out of order
print_r($secondResult);
致命错误:未捕获PDO异常:数据包顺序错误。
预期0收到1。数据包大小=23英寸
html\www\website\core\Database.php:41堆栈
跟踪:
这是你的电话号码
这可能会有帮助:@Barmar我看到了,并尝试了各种组合,但我不确定如何将mysqli发布的解决方案转换为PDO…在laravel中有什么想法吗?在哪里设置这个东西?在PDO对象上调用setAttribute函数。例如:$db=新的PDO(…)$db->setAttribute(PDO::ATTR\u EMULATE\u PREPARES,true);