У меня есть проблемы с пакетной вставкой объектов в базу данных с помощью симфонии 1.4 и доктрина 1.2.
Моя модель имеет определенный вид объекта под названием "Сектор", каждый из которых имеет несколько объектов типа "Cupo" (обычно в пределах от 50 до 200 000). Эти объекты являются довольно маленькими; просто короткая строка идентификатора и одно или два целых числа. Каждый раз, когда группа Секторов создается пользователем, я должен автоматически добавить все эти экземпляры "Cupo" к базе данных. В случае, если что-либо идет не так, как надо, я использую транзакцию доктрины для отката всего. Проблема состоит в том, что я могу только создать приблизительно 2 000 экземпляров, прежде чем php исчерпает память. Это в настоящее время имеет предел 128 МБ, который должен быть более чем достаточно для обработки объектов тем использованием меньше чем 100 байтов. Я попытался увеличить предел памяти до 512 МБ, но 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;
}
Еще раз этот код хорошо работает меньше чем для 1 000 объектов, но чего-либо большего, чем 1 500 сбоев. Спасибо за справку.
Попробуйте сломать круговую ссылку, которая обычно вызывает утечки памяти с
$cupo->save();
$cupo->free(); //this call
как описано в руководстве по доктрине.
Старайтесь unset ($ Cupo);
после каждой экономии. Это должно помочь. Другое дело - разделить скрипт и сделать некоторую пакетную обработку.
Периодически закрывайте и снова открывайте соединение - не знаю, почему, но похоже, что PDO сохраняет ссылки.
Я только что выполнил "демонизированный" скрипт с Symfony 1.4, и установка следующих параметров остановила перегрузку памяти:
sfConfig::set('sf_debug', false);