简体   繁体   English

PHP 5.3.5 PDO FETCH_OBJ内存泄漏?

[英]PHP 5.3.5 PDO FETCH_OBJ memory leak?

I'm currently developing an application in PHP which uses PDO. 我目前正在开发一个使用PDO的PHP应用程序。 I'm writing an import which reads in a CSV file, checks the database for a record, and updates, deletes, etc.... 我正在写一个导入文件,它读入一个CSV文件,检查数据库中的记录,以及更新,删除等等....

Something which I've noticed is the memory being used by this script seems very high and it seems like it could be to do with the way I'm executing the query. 我注意到的是这个脚本使用的内存似乎非常高,似乎可能与我执行查询的方式有关。 see below for example query which is executed for each line in the CSV: 请参阅下面的示例查询,该查询是针对CSV中的每一行执行的:

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

for the above memory_get_peak_usage() = 6291456 对于上面的memory_get_peak_usage()= 6291456

When using the below: 使用以下时:

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

for the above memory_get_peak_usage() = 524288 对于上面的memory_get_peak_usage()= 524288

As you can see the difference is fairly big. 你可以看到差异相当大。

I guess I've 3 questions.. 我想我有3个问题..

  1. Is there a memory leak when using PDO::FETCH_OBJ in PHP 5.3.5? 在PHP 5.3.5中使用PDO :: FETCH_OBJ时是否存在内存泄漏?
  2. Is there any difference between using FETCH_CLASS as opposed to FETCH_OBJ? 使用FETCH_CLASS与FETCH_OBJ相比有什么区别吗?
  3. Has anyone else experienced the same issue? 还有其他人遇到过同样的问题吗?

Company Class is simple: 公司类很简单:

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

Looking at the PHP changelog , there does appear to be a relevant fix in 5.3.4 where a memory leak was fixed in PDO FETCH_INTO . 查看PHP更新日志 ,似乎在5.3.4中确实存在相关修复,其中PDO FETCH_INTO修复了内存泄漏

From what you've said, I suspect that yes, this is the bug you're seeing. 从你所说的,我怀疑是的,这是你看到的错误。 The solution, of course, is to upgrade -- there really is no point in sticking with an old patch release. 当然,解决方案是升级 - 坚持使用旧的补丁版本毫无意义。

Even if this isn't the bug you're seeing, there have been a very large number of PDO fixes in the versions between 5.3.3 and now; 即使这不是您所看到的错误,在5.3.3和现在之间的版本中已经有大量的PDO修复程序; I'm sure there's a good chance that at least some of them are relevant to you. 我敢肯定,至少其中一些与你相关的机会很大。

Note : the original answer was given before the OP changed PDO::FETCH_OBJ to PDO::FETCH_INTO :原始给定答案OP改变之前PDO::FETCH_OBJPDO::FETCH_INTO

After that update I've tried to reproduce the behaviour using PHP 5.3.10-1ubuntu3.4 . 在更新之后,我尝试使用PHP 5.3.10-1ubuntu3.4重现该行为。 There where no significant difference in memory cosumption between both fetch modes. 两种获取模式之间的内存消耗没有显着差异。 I've tested using a large MySQL table and a large SQLite database. 我已经使用大型MySQL表和大型SQLite数据库进行了测试。

As @SDC mentioned the bug is known and was fixed after 5.3.5. 正如@SDC提到的那样,bug已知并在5.3.5之后修复。 (At least in 5.3.10 as I've seen). (至少在我看过的5.3.10中)。

Conclusion: You have to upgrade your PHP version. 结论:您必须升级 PHP版本。


Although the behaviour is interesting and should be investigated you are using PDO::setFetchMode() in a wrong way. 虽然行为很有趣并且应该进行调查,但您使用PDO::setFetchMode()的方式是错误的。 When $mode - the first param - is PDO::FETCH_OBJ no second param is expected. 当$ mode - 第一个参数 - 是PDO :: FETCH_OBJ时, 不需要第二个参数。 If you use a second param the call to setFetchMode() will fail (returnin false) and the default fetch mode FETCH_BOTH will be used. 如果使用第二个参数,则对setFetchMode()的调用将失败(returnin false),并将使用默认的获取模式FETCH_BOTH

You can see this error when enabling PDO::ERRMODE_EXCEPTION : 启用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());

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: fetch mode doesn't allow any extra arguments' 致命错误:带有消息'SQLSTATE [HY000]的未捕获异常'PDOException':常规错误:获取模式不允许任何额外参数'

When you are expecting that result rows should objects of a specific class, then PDO::FETCH_CLASS is the working attempt. 当您期望结果行应该是特定类的对象时,那么PDO::FETCH_CLASS就是工作尝试。 PDO::FETCH_OBJ will return objects from type StdClass PDO::FETCH_OBJ将返回StdClass类型的StdClass

FETCH_INTO: Means fetching into an existing Object (that was created with new eg) FETCH_INTO:意味着获取现有的Object(使用new创建)

FETCH_CLASS: Means fetching into an new Object (the constructor is called every row) FETCH_CLASS:意味着获取新的Object(每行调用构造函数)

Be careful, if the constructor in your Company class has dependencies, they are called for every row. 请注意,如果您的Company类中的构造函数具有依赖项,则会为每一行调用它们。 Therefore the constructor should not contain functions or classes that do an DB connect eg only simple initializing... 因此构造函数不应该包含进行DB连接的函数或类,例如只需要简单的初始化...

How does your Company class look like? 您的公司课程如何?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM