我目前正在开发一个使用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个问题..
公司类很简单:
class Company {
function __construct(){}
/**classvars**/
public $_tablename = 'company';
public $transient;
public $id;
public $name;
/**endclassvars**/
}
答案 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类中的构造函数具有依赖项,则会为每一行调用它们。因此,构造函数不应包含进行数据库连接的函数或类,例如只是简单的初始化......
您的公司课程如何?