重用PDO语句会导致进程崩溃

时间:2013-06-03 18:22:32

标签: php mysql pdo

我正在重用一个变量来存储两个不同的PDO mysql语句:

$stmt=$dbh->prepare("SELECT ....");   
$stmt->execute();

$stmt=$dbh->prepare("UPDATE ....");
//crash here: 
//*** Error in `/opt/lampp/bin/httpd': free(): invalid pointer: 0xf4a028dc ***
//*** Error in `/opt/lampp/bin/httpd': free(): invalid pointer: 0xf4a028dc ***
//[Mon Jun 03 19:53:48.691674 2013] [core:notice] [pid 20249] AH00052: child pid 25933 exit //signal Aborted (6)
//[Mon Jun 03 19:53:48.691727 2013] [core:notice] [pid 20249] AH00052: child pid 25952 exit //signal Aborted (6)

但如果我使用$ stmt2 = $ dbh-> prepare(" UPDATE ....");没有什么奇怪的事情发生,并且法律执行正常。如果我启用准备仿真,它也没有问题:

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

我在执行第一个语句后尝试了$stmt->closeCursor(),并且unset($stmt)(以及它们两个)也尝试了{{1}},产生了相同的崩溃。我使用的是PHP 5.4.7。为什么会这样?这是一个错误还是一个非常奇怪的功能?

[更新] 我从xampp切换到OpenSUSE 12.3默认Apache(2.2.22)和PHP(5.3.17)仍然得到相同的错误,但更详细的转储日志:{{ 3}}

[更新2] 我也确认在使用MySQL 5.5.27而不是MariaDB 5.5.29作为服务器时会发生这种情况,所以它肯定会从我的脚本中出现并且几乎是通用的(如果它与我的发行版中的一些glibc相关的问题也会尝试使用centos虚拟机...),发生在不同版本的apache,mysql和php中,但仍然没有。我知道可能是什么原因...

[更新3] 好吧看起来CentOS 6.4对它来说好多了,让我运行我的脚本没有任何麻烦,因为它是我正在使用的在制作上我觉得没有什么可担心的。无论如何,我真的很想知道这里发生了什么......

1 个答案:

答案 0 :(得分:3)

我为这个后期更新道歉,但我在PDO(Sybase)方面遇到了类似的问题,我可以确认在不设置或设置为null的情况下重新使用语句变量绝对应该避免。

在PHP中,每当我们覆盖变量值时,它首先创建新变量,然后才会替换并销毁旧值。在大多数情况下,这不是一个问题(除了花费双倍的内存来分配单个变量),但与语句完全不同,因为它不会关闭第一个语句或光标创建第二个语句和一些数据库驱动程序不能很好地处理同一PDO连接中的多个语句。

根据您使用的驱动程序,PDOStatement::closeCursor()可能不会关闭语句,因此问题仍然存在(在http://www.php.net/manual/en/pdostatement.closecursor.php我们可以看到它取决于驱动程序,否则它将使用PDO默认值不会结束陈述。)

因此,在这种情况下,unset()之间的PDO::prepare()会产生重大影响:

$stmt=$dbh->prepare("SELECT ....");   
$stmt->execute();
unset($stmt); // or $stmt = null; --> statement is destroyed at PDO
$stmt=$dbh->prepare("UPDATE ....");