PHP5.3.5 PDO FETCH_OBJ内存泄漏?
我目前正在用PHP开发一个使用PDO的应用程序。我正在写一个导入,它读取一个CSV文件,检查数据库中的记录,更新,删除,等等 我注意到,这个脚本使用的内存似乎非常高,这似乎与我执行查询的方式有关。请参见下面为CSV中的每一行执行的查询示例:PHP5.3.5 PDO FETCH_OBJ内存泄漏?,php,memory,pdo,memory-leaks,Php,Memory,Pdo,Memory Leaks,我目前正在用PHP开发一个使用PDO的应用程序。我正在写一个导入,它读取一个CSV文件,检查数据库中的记录,更新,删除,等等 我注意到,这个脚本使用的内存似乎非常高,这似乎与我执行查询的方式有关。请参见下面为CSV中的每一行执行的查询示例: $qry = "SELECT * FROM company WHERE id = 1"; $sth = $this->prepare($qry); $sth->execute(); $sth->setFetchMode(PDO::FETCH
$qry = "SELECT * FROM company WHERE id = 1";
$sth = $this->prepare($qry);
$sth->execute();
$sth->setFetchMode(PDO::FETCH_INTO, new Company());
$sth->fetch();
对于上述内存,获取峰值使用率()=6291456
当使用以下工具时:
$qry = "SELECT * FROM company WHERE id = 1";
$sth = $this->prepare($qry);
$sth->execute();
$sth->setFetchMode(PDO::FETCH_CLASS, "Company");
$sth->fetch();
对于上面的内存_get_peak_usage()=524288
正如你所看到的,差别是相当大的
我想我有三个问题
class Company {
function __construct(){}
/**classvars**/
public $_tablename = 'company';
public $transient;
public $id;
public $name;
/**endclassvars**/
}
注意:在OP将
PDO::FETCH_OBJ
更改为PDO::FETCH_INTO
在那次更新之后,我尝试使用PHP5.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\u这两个
启用PDO::ERRMODE\u异常时,您可以看到此错误:
$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());
致命错误:未捕获异常“PDOException”,消息为“SQLSTATE[HY000]:一般错误:获取模式不允许任何额外参数”
当您希望结果行应该是特定类的对象时,那么PDO::FETCH_class
就是工作尝试PDO::FETCH_OBJ
将从类型StdClass
FETCH_INTO返回对象:表示提取到现有对象(使用新对象创建,例如)
FETCH_类:意味着进入一个新对象(每行调用一个构造函数)
请注意,如果您公司类中的构造函数具有依赖项,则每行都会调用它们。因此,构造函数不应包含进行DB连接的函数或类,例如,仅简单初始化
您的公司类是什么样子的?查看,在5.3.4中似乎有一个相关的修复程序,其中
根据你所说的,我怀疑是的,这就是你看到的bug。当然,解决方案是升级——坚持使用旧的补丁版本是没有意义的
即使这不是你看到的bug,在5.3.3到现在的版本中已经有大量的PDO修复;我敢肯定,其中至少有一部分与你有关。@MikeB:但他问的问题是,为什么会有如此巨大的差异。@Martin你可能误解了PDO::FETCH_OBJ
。看我的answer@MikeB公司类的内容与此无关。。。他正在以任何一种方式实例化一个公司对象。Company类做什么并不重要,因为它在这两种情况下都做相同的事情。对不起,我输入了错误的代码。。它不是PDO::FETCH_OBJ,我拥有的是PDO::FETCH_INTO。问题仍然存在。我已经编辑了我的帖子如果您怀疑5.3.5中可能存在内存泄漏,那么您应该尝试的第一个解决方案是更新到最新的补丁版本,目前为5.3.21。在5.3.5和5.3.21之间修复了很多bug和安全问题。无论如何,你真的应该让你的软件保持最新的补丁。对不起,我输入了错误的代码。。它不是PDO::FETCH_OBJ,我拥有的是PDO::FETCH_INTO。问题仍然存在。我已经编辑了我的post@Martin好,我们会进一步调查。目前正在浏览pdo_stmt.c:)好的,我想这是因为:$sth->setFetchMode(pdo::FETCH_INTO,new Company());如果您正在调用$sth->setFetchMode(PDO::FETCH_类,“Company”);PHP必须确定并创建类,在第一种情况下,它就在那里。感谢您指出这一点。我猜这只是我发布的版本中的一部分。我必须试着升级,然后检查一下。再次感谢