这是一个适用于你们任何一个Doctrine用户的人。我有一个PHP CLI守护程序进程,每n秒检查一次表以查找尚未处理的条目。它基本上是一个FIFO。无论如何,我总是超过分配给PHP的内存,因为Doctrine不会释放它的资源。为了解决这个问题,它为查询对象提供了免费。我似乎无法让它工作。这是代码:

 22     print "You are using " . (memory_get_usage() / 1024). "\n";
 23     $query = Doctrine_Query::create()
 24                 ->from('SubmissionQueue s')
 25                 ->where('s.time_acted_on IS NULL')
 26                 ->orderby('s.time_queued')
 27                 ->limit(1)
 28                 ->execute();
 29     print $query[0]->time_queued . "\n";
 30     $query->free();

任何想法我做错了什么?

编辑:我使用的是1.0.3

编辑:我已经尝试了以下所有建议。在找到unset()之前,我非常希望free(),因为我已经在那里了。

以下是可能有助于提供任何帮助的更多代码。在你质疑连接的打开和关闭之前,它将成为生成孩子的守护进程,而且我经历过连接必须是唯一的。

  1 <?php
  2
  3 require_once('/usr/local/lib/php/Doctrine/lib/Doctrine.php');
  4
  5 spl_autoload_register(array('Doctrine', 'autoload'));
  6
  7 $manager = Doctrine_Manager::getInstance();
  8 $manager->setAttribute('model_loading','conservative');
  9 Doctrine::loadModels('lib/model/master');
 10
 11 while(1){
 12     print "You are using " . intval(memory_get_usage() / 1024) . "\n";
 13     $manager->connection('********************************************','master');
 14     $query = Doctrine_Query::create()
 15                 ->from('SubmissionQueue s')
 16                 ->where('s.time_acted_on IS NULL')
 17                 ->orderby('s.time_queued')
 18                 ->limit(1)
 19                 ->execute();
 20     print "[" . $query[0]->time_queued . "]\n";
 21     $query->free();
 22     unset($query);
 23     $query = null;
 24     $manager->closeConnection(Doctrine_Manager::getInstance()->getConnection('master'));
 25     sleep(5);
 26 }
 27

一些示例输出:

You are using 14949KB
[2008-11-17 13:59:00]
You are using 14978KB
[2008-11-17 13:59:00]
You are using 15007KB
[2008-11-17 13:59:00]
You are using 15035KB
[2008-11-17 13:59:00]
You are using 15064KB
[2008-11-17 13:59:00]
You are using 15093KB
[2008-11-17 13:59:00]
You are using 15121KB
[2008-11-17 13:59:00]
You are using 15150KB
[2008-11-17 13:59:00]
You are using 15179KB
[2008-11-17 13:59:00]
You are using 15207KB
[2008-11-17 13:59:00]
You are using 15236KB
[2008-11-17 13:59:00]
You are using 15265KB
[2008-11-17 13:59:00]
You are using 15293KB
[2008-11-17 13:59:00]
You are using 15322KB
有帮助吗?

解决方案

问题是,free()不会从内存中删除Doctrine对象,只是消除了对这些对象的循环引用,使垃圾收集器可以清理这些对象。请参阅 23.6免费对象 主义手册

  

从版本5.2.5开始,PHP无法使用   垃圾收集对象图   有循环引用,例如亲   提到有儿童的儿童   对父母的引用。很多   学说模型对象有这样的   关系,PHP不会释放他们的   即使物体离开也要记忆   范围。

     

对于大多数PHP应用程序,这个   问题没什么影响,   因为PHP脚本往往是   短暂的。更长寿的脚本,   例如批量数据导入程序和   出口商,可能会耗尽内存   除非你手动打破通告   参考链。学说提供了一个   Doctrine_Record上的free()函数,   Doctrine_Collection,和   Doctrine_Query消除了   这些对象的循环引用,   释放他们垃圾   集合。

使用unset()

后,解决方案应该是$query <=>对象
$query = Doctrine_Query::create()
            ->from('SubmissionQueue s')
            ->where('s.time_acted_on IS NULL')
            ->orderby('s.time_queued')
            ->limit(1);
$query->execute();
print $query[0]->time_queued . "\n";
$query->free();
unset($query); // perhaps $query = null; will also work

其他提示

Doctrine_Query也有一个free()方法,目前你只是在你的Doctrine_Collection上调用free(),例如,尝试:

 $query = Doctrine_Query::create()
             ->from('SubmissionQueue s')
             ->where('s.time_acted_on IS NULL')
             ->orderby('s.time_queued')
             ->limit(1);
 $results = $query->execute();
 print $results[0]->time_queued . "\n";

 $results->free();
 $query->free();

没有使用Doctrine的经验(只是因为我在本周末发现了它的一些兴趣......),所以接受或离开我的猜测...... ^ _ ^

我会尝试将查询创建与其执行部分分开:

$query = Doctrine_Query::create()
            ->from('SubmissionQueue s')
            ->where('s.time_acted_on IS NULL')
            ->orderby('s.time_queued')
            ->limit(1);
$query->execute();
print $query[0]->time_queued . "\n";
$query->free();

不确定什么执行返回,但为了以防万一,值得尝试...除非有人有更开明的建议! :-P

尝试$ query - <!> gt; free(true);

(?)

我想我可能只会将PDO用于真正不需要ORM的后端部分,因为没有那么多查询。我真的很想在这个系统中的所有应用程序中使用单一方式与数据库进行交互。也许我会多考虑一下。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top