4

我目前正在开发一个使用 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. 有没有其他人遇到过同样的问题?

公司类很简单:

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

3 回答 3

3

查看PHP 更改日志,在 5.3.4 中似乎有一个相关的修复,其中PDO 中修复了内存泄漏FETCH_INTO

从你所说的,我怀疑是的,这是你看到的错误。当然,解决方案是升级——坚持旧的补丁版本确实没有意义。

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

于 2013-01-23T14:53:21.323 回答
2

注意:原始答案是在 OP 更改PDO::FETCH_OBJ为之前给出的PDO::FETCH_INTO

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

正如@SDC 提到的,该错误是已知的,并在 5.3.5 之后修复。(至少在我所见的 5.3.10 中)。

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


虽然这种行为很有趣并且应该调查你PDO::setFetchMode()以错误的方式使用。当 $mode - 第一个参数 - 是 PDO::FETCH_OBJ 时,不需要第二个参数。如果您使用第二个参数,调用setFetchMode()将失败(返回 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());

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

当您期望结果行应该是特定类的对象时,那PDO::FETCH_CLASS就是工作尝试。PDO::FETCH_OBJ将从类型返回对象StdClass

于 2013-01-23T14:06:20.207 回答
0

FETCH_INTO:表示提取到现有对象(使用新创建的例如)

FETCH_CLASS:表示获取一个新对象(每行调用构造函数)

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

您的公司课程是什么样的?

于 2013-01-23T14:42:11.943 回答