重用PDO语句var会使进程崩溃 [英] Reusing PDO statement var crashes the process

查看:61
本文介绍了重用PDO语句var会使进程崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm reusing a variable to store two different PDO mysql statements:

$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 ....");没有任何奇怪的事情发生,并且陈述执行得很好.如果启用了准备仿真,它也不会出现问题:

but if instead I use $stmt2=$dbh->prepare("UPDATE ...."); nothing weird happens and the statment executes alright. It also goes without trouble if I enable prepare emulation:

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

我在执行了第一条语句之后又尝试了$stmt->closeCursor(),并且还执行了unset($stmt)(以及它们两者),产生了相同的崩溃.我正在使用PHP 5.4.7.为什么会这样?这是一个错误还是一个很奇怪的功能?

I tried $stmt->closeCursor() after executing the first statement and also unset($stmt) (and also both of them), producing the same crash. I'm using PHP 5.4.7. Why does this happen? Is it a bug or a really weird feature?

[UPDATE] 我从xampp切换到OpenSUSE 12.3默认的Apache(2.2.22)和PHP(5.3.17),仍然收到相同的错误,但转储日志更加详细: http://paste2.org/d0BtdOHI

[UPDATE] I switched from xampp to OpenSUSE 12.3 default Apache (2.2.22) and PHP (5.3.17) and still get the same error, but a more detailed dump log: http://paste2.org/d0BtdOHI

[UPDATE 2] 我还确认了使用MySQL 5.5.27代替MariaDB 5.5.29作为服务器时会发生这种情况,因此它确实来自我的脚本,并且非常通用(也可以尝试使用centos虚拟机,以防万一我发行版中存在与glibc相关的问题...),发生在不同版本的apache,mysql和php中,但仍然不知道可能是什么原因.

[UPDATE 2] I've also confirmed it happens when using MySQL 5.5.27 instead of MariaDB 5.5.29 as a server, so it's definetly comming from my script and pretty much universal (going to try also a centos virtual machine just in case it's some glibc related issue from my distro...), happening with different versions of apache, mysql and php, but still don't have a clue of what can be the cause...

[UPDATE 3] 好吧,看来CentOS 6.4对此要好得多,并且可以让我运行脚本而没有任何麻烦,而且由于这是我在生产中使用的东西,所以我猜没什么担心.无论如何,我真的很想知道这里发生了什么...

[UPDATE 3] Well it seems CentOS 6.4 is much nicer about it and lets me run my script without any troubles at all, and since it's what I'm using on production I guess there's nothing to worry about. Anyway I would really like to know what's happening here...

推荐答案

对于此次更新,我深表歉意,但是我对PDO(Sybase)也有类似的问题,并且我可以确认重用语句变量而无需取消设置绝对应该避免为null.

I apologize for this late update, but I had a similar problem with PDO (Sybase), and I can confirm that re-using statement variables without unsetting or setting to null should definitely be avoided.

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

In PHP, whenever we overwrite a variable value, it first creates the new variable, and only after that it replaces and destroys the old value. In most cases that's not a problem (other than spending double the memory for allocating a single variable), but with statements it's completely different, because it wouldn't close the first statement or the cursor when it creates the second one, and some database drivers don't handle well multiple statements within the same PDO connection.

根据所使用的驱动程序,PDOStatement::closeCursor()可能不会关闭该语句,因此问题仍然存在(位于

Depending on the driver you use, the PDOStatement::closeCursor() might not close the statement, so the problem persists (at http://www.php.net/manual/en/pdostatement.closecursor.php we can see that it depends on the driver, otherwise it will use PDO default that does not closes statements).

因此,在这种情况下,PDO::prepare()之间的unset()会带来所有不同:

So in this case, an unset() between the PDO::prepare() makes all the difference:

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

这篇关于重用PDO语句var会使进程崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆