2010-01-19 44 views
16

我使用的symfony 1.4和1.2学说具有到数据库与对象的批量插入的问题。php/symfony/doctrine内存泄漏?

我的模型具有一定类型的对象称为“扇区”,其中的每一个具有类型“Cupo”的多个对象(通常范围从50到20万)。这些物体非常小,只是一个简短的标识符字符串和一个或两个整数。每当用户创建一组扇区时,我需要自动将所有这些“Cupo”实例添加到数据库中。如果出现任何问题,我正在使用原则事务来回滚所有内容。问题是我只能在php耗尽内存之前创建大约2000个实例。它目前有128MB的限制,对于处理少于100个字节的对象应该足够了。我试图增加内存限制到512MB,但PHP仍然崩溃,并没有解决问题。我是否正确地批量插入或者有更好的方法?

这里的错误:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 71 bytes) in /Users/yo/Sites/grifoo/lib/vendor/symfony/lib/log/sfVarLogger.class.php on line 170 

而这里的代码:再次

public function save($conn=null){ 

    $conn=$conn?$conn:Doctrine_Manager::connection(); 

    $conn->beginTransaction(); 


    try { 
     $evento=$this->object; 


     foreach($evento->getSectores() as $s){ 

      for($j=0;$j<$s->getCapacity();$j++){ 

       $cupo=new Cupo(); 
       $cupo->setActivo($s->getActivo()); 
       $cupo->setEventoId($s->getEventoId()); 
       $cupo->setNombre($j); 
       $cupo->setSector($s); 

       $cupo->save(); 

      } 
     } 

     $conn->commit(); 
     return; 
    } 
    catch (Exception $e) { 
     $conn->rollback(); 
     throw $e; 
    } 

,此代码工作正常,少于1000个对象,但任何事情比1500更大的失败。谢谢您的帮助。

+1

标记某人的回答是正确的,呃? – develop7 2010-01-24 17:21:38

+0

对于批量插入,您可能还想考虑通过PDO执行原始SQL插入,它肯定会更快,并且不会泄漏内存。 – 2012-11-28 00:30:35

回答

1

尝试unset($cupo);每节约之后。这应该是帮助。另一件事是分割脚本并做一些批处理。

1

试图打破循环引用其通常以

$cupo->save(); 

$cupo->free(); //this call 

导致内存泄漏如学说手册中described

0

定期关闭并重新打开连接 - 不知道为什么,但它似乎是PDO保留引用。

3

我刚才做了与symfony的1.4和设置下面的“进程化”脚本停止内存占用:

sfConfig::set('sf_debug', false); 
+0

如果您在创建数据库管理器之前执行此操作,这对我有用。如果你在做任务,我认为这是安全的。 – 2011-05-04 20:14:00

33

试着做

$cupo->save(); 
$cupo->free(); 
$cupo = null; 

(但用我的代码),我仍然会导致内存溢出。任何其他想法,所以呢?

更新:

all: 
    doctrine: 
    class: sfDoctrineDatabase 
    param: 
     dsn: 'mysql:host=localhost;dbname=.......' 
     username: ..... 
     password: ..... 
     profiler: false 

探查:假项禁用主义的查询记录,通常保持一个

我在databases.yml里,看起来像创造了一个新的环境您制作的每个查询的副本。它并没有阻止内存泄漏,但通过我的数据导入,我能够获得大约两倍的内存,因为我没有它。

更新2

我加

Doctrine_Manager::connection()->setAttribute(Doctrine_Core::ATTR_AUTO_FREE_QUERY_OBJECTS, true); 

运行我的查询之前,并改变

$cupo = null; 

unset($cupo); 

现在我的剧本已经快乐地离开了。我很肯定它会在这次没有用完RAM的情况下结束。

更新3

是啊。这是赢得的组合。

+1

我有类似的问题。我尝试了这些东西,我的表现明显改善。 – 2010-11-16 18:05:12

+0

如果可能,升级到php5.3并使用 - > free()。内存泄漏是由PHP5.2的垃圾收集器无法清除不再从其循环外部引用的循环引用引起的。 PHP5.3有一个更好的收集器,并且free()试图在变量离开作用域之前撤消这些引用。 – 2011-01-06 08:14:56

+1

@Jordan - 哇我只是有一个类似的问题 - 但在选择 - 探查器:虚假有巨大的影响...谢谢 – ManseUK 2011-08-23 14:25:53

2

学说泄漏,你可以做的事情不多。请确保您使用$ q-> free(),以尽可能减少影响。 学说不适用于维护脚本。解决此问题的唯一方法是将脚本分解为执行部分任务的部分。一种方法是在脚本中添加一个start参数,并在处理了一定数量的对象后,脚本以较高的起始值重定向到自身。这对我来说很好,尽管它使编写维护脚本变得更加繁琐。

+0

我做出了所有这些小技巧都没有帮助的相同体验。我为您描述了一种类似的方法:http://stackoverflow.com/a/11474869/620410 – Tapper 2012-07-13 16:55:28

0

什么工作对我来说是调用free方法是这样的:

$cupo->save(); 
$cupo->free(true); // free also the related components 
unset($cupo); 
3

对于symfony的任务,我也面临这个问题,并做了下面的事情。它为我工作。

  • 禁用调试模式。添加数据库连接之前,以下使用后初始化

    sfConfig::set('sf_debug', false); 
    
  • 设置自动查询对象自由属性为DB连接

    $connection->setAttribute(Doctrine_Core::ATTR_AUTO_FREE_QUERY_OBJECTS, true); 
    
  • 释放所有对象

    $object_name->free() 
    
  • 没有设置所有的阵列使用unset($array_name)

  • Che ck在任务上使用的所有教义查询。使用后免费查询所有查询。 $q->free() (这是使用查询的任何时间一个很好的做法。)

这就是全部。希望它可以帮助某人。

1

对于我来说,我只是初始化这样的任务:

// initialize the database connection 
$databaseManager = new sfDatabaseManager($this->configuration); 
$connection = $databaseManager->getDatabase($options['connection'])->getConnection(); 
$config = ProjectConfiguration::getApplicationConfiguration('frontend', 'prod', true); 
sfContext::createInstance($config); 

(WITH PROD CONFIG)
并使用免费()后保存()主义的对象

内存上在25Mo

memory_get_usage=26.884071350098Mo 

稳定的PHP 5.3 Debian的挤压