这是一个非常简化的例子来说明我所看到的行为。如果您创建下表并运行以下php脚本,您将获得我正在描述的行为:
<?php
/*
CREATE TABLE Testing (id INT NOT NULL PRIMARY KEY, name VARCHAR(255) NOT NULL);
INSERT INTO Testing VALUES (1,'One'),(2,'Two'),(3,'Three'),(4,'Four'),(5,'Five');
*/
$mysqli = new mysqli($dbhost, $dbuser, $dbpasswd, $dbname);
$stmtQuery = $mysqli->prepare("SELECT id, name FROM Testing WHERE id = ?");
$stmtQuery->bind_result($id, $name);
for ($i=1; $i <= 5; $i++) {
$stmtQuery->bind_param('i', $i);
$stmtQuery->execute();
$stmtQuery->store_result();
$stmtQuery->fetch();
$stmtQuery->free_result();
error_log("$id, $name");
}
$stmtQuery->close();
?>
在使用libmysql作为驱动程序的机器上(在我的情况下为5.3.10),这会产生以下输出:
1, One
2, Two
3, Three
4, Four
5, Five
在使用MySQLnd作为驱动程序(5.3.10和5.4.24)的计算机上,这会产生以下结果:
1, One
1, One
1, One
1, One
1, One
我很难过为什么。我可以看到它的方法,但我想真正理解发生了什么。
之所以重要,是因为我们将要迁移到5.5并且5.5以下的默认驱动程序是MySQLnd。如果我们在使用如何以及何时使用由MySQLnd驱动程序工作方式暴露的store_result时出错了,我现在要抓住并修复它,而不是以后。
那么,有什么想法吗?
答案 0 :(得分:1)
您已正确确定问题是mysqli_stmt::free_result()
。这是为什么在PHP中手动关闭并释放mysqli内部资源不是一个好主意的另一个原因。您不需要这样做,让PHP自动处理它。
mysqli_stmt::free_result()
在PHP手册中没有很好地记录。此函数执行以下操作:
释放与该语句关联的内部结果存储器,包括缓冲和非缓冲数据以及绑定到该语句的所有变量引用。
这意味着当您调用此函数时,它将取消绑定与bind_result()
绑定的变量。 您必须在循环内绑定变量或删除$stmtQuery->free_result()
。由于变量仅绑定到第一个结果,因此它们的值将始终向您显示第一个结果的值。
我无法确认是否存在差异,因为我无法使用libmysqlclient访问计算机,但是差异可能来自以下两个原因:
由于内部原因,用于PHP的MySQL本机驱动程序实现此功能的方式有所不同。
mysqlnd或libmysqlclient存在/有错误。