PHP 5.3.5 PDO FETCH_OBJ内存泄漏?

时间:2013-01-23 13:57:48

标签: php memory pdo memory-leaks

我目前正在开发一个使用PDO的PHP应用程序。我正在写一个导入文件,它读取一个CSV文件,检查数据库中的记录,以及更新,删除等....

我注意到的是这个脚本使用的内存似乎非常高,似乎可能与我执行查询的方式有关。请参阅下面的示例查询,该查询是针对CSV中的每一行执行的:

$qry = "SELECT * FROM company WHERE id = 1";
$sth = $this->prepare($qry);
$sth->execute();
$sth->setFetchMode(PDO::FETCH_INTO, new Company());
$sth->fetch();

对于上述memory_get_peak_usage()= 6291456

使用以下内容时:

$qry = "SELECT * FROM company WHERE id = 1";
$sth = $this->prepare($qry);
$sth->execute();
$sth->setFetchMode(PDO::FETCH_CLASS, "Company");
$sth->fetch();

对于上面的memory_get_peak_usage()= 524288

正如您所看到的,差异相当大。

我想我有3个问题..

  1. 在PHP 5.3.5中使用PDO :: FETCH_OBJ时是否存在内存泄漏?
  2. 使用FETCH_CLASS与FETCH_OBJ相比有什么区别吗?
  3. 还有其他人遇到过同样的问题吗?
  4. 公司类很简单:

    class Company {
        function __construct(){}
        /**classvars**/
        public $_tablename = 'company';
        public $transient;
        public $id;
        public $name;
        /**endclassvars**/
    } 
    

3 个答案:

答案 0 :(得分:3)

查看PHP changelog,似乎在5.3.4中找到了memory leak was fixed in PDO FETCH_INTO的相关修补程序。

从你所说的,我怀疑是的,这是你看到的错误。当然,解决方案是升级 - 坚持使用旧的补丁版本毫无意义。

即使这不是你所看到的错误,在5.3.3和现在之间的版本中已经有大量的PDO修复;我敢肯定,至少有一些与你相关的很有可能。

答案 1 :(得分:2)

注意:在OP将PDO::FETCH_OBJ更改为PDO::FETCH_INTO之前提供了原始答案

在更新之后,我尝试使用PHP 5.3.10-1ubuntu3.4重现行为。两种获取模式之间的内存消耗没有显着差异。我已经使用大型MySQL表和大型SQLite数据库进行了测试。

正如@SDC提到的那样,这个bug是已知的,并在5.3.5之后修复。 (至少在我看过的5.3.10中)。

结论:您必须升级您的PHP版本。


虽然行为很有趣并且应该进行调查,但您使用PDO::setFetchMode()的方式是错误的。当$ mode - 第一个参数 - 是PDO :: FETCH_OBJ 没有期望第二个参数。如果您使用第二个参数,则对setFetchMode()的调用将失败(returnin false),并将使用默认的提取模式FETCH_BOTH

启用PDO::ERRMODE_EXCEPTION时,您可以看到此错误:

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$stmt = $db->query('....');

// the following line will trigger an exception
$stmt->setFetchMode(PDO::FETCH_OBJ, new Company());
  

致命错误:带有消息'SQLSTATE [HY000]的未捕获异常'PDOException':常规错误:获取模式不允许任何额外参数'

如果您希望结果行应该是特定类的对象,那么PDO::FETCH_CLASS就是工作尝试。 PDO::FETCH_OBJ将返回StdClass

类型的对象

答案 2 :(得分:0)

FETCH_INTO:表示获取现有对象(使用new创建的对象)。

FETCH_CLASS:意味着获取新的Object(每行调用构造函数)

请注意,如果您的Company类中的构造函数具有依赖项,则会为每一行调用它们。因此,构造函数不应包含进行数据库连接的函数或类,例如只是简单的初始化......

您的公司课程如何?