PHP 致命错误:允许的 xxx 字节内存大小已耗尽(尝试分配 XX 字节)


PHP Fatal error: Allowed memory size of xxx bytes exhausted (tried to allocate XX bytes)

我有一个php脚本,可以拆分一个大文件并插入PostgreSQL。此导入之前在 PHP 5.3 和 PostgreSQL 8.3 以及 Mac OS X 10.5.8 上工作过。我现在将所有内容都移到了新的Mac Pro上。这有大量的RAM(16MB),Mac OS X 10.9.2,PHP 5.5.8,PostgreSQL 9.3。

读取大型导入文件时出现问题。它是一个超过 181 MB 的制表符分隔文件。我试图将PHP内存增加到2GB(!),但没有更多的成功。所以我想问题一定出在读取文本文件并拆分它的代码中。我收到此错误:

PHP Fatal error:  Allowed memory size of 2097152000 bytes exhausted (tried to allocate 72 bytes) in /Library/FileMaker Server/Data/Scripts/getGBIFdata.php on line 20

有没有更好的方法可以做到这一点?我阅读了文件并拆分了行,然后再次按''t(制表符)拆分了每一行。我在这一行得到的错误:

$arr = explode("'t", $line);

这是我的代码:

<?php
 ## I have tried everything here, memory_limit in php.ini is 256M
 ini_set("memory_limit","1000M");
$db= pg_connect('host=127.0.0.1 dbname=My_DB_Name user=Username password=Pass');
### SETT ERROR_STATE:
pg_set_error_verbosity($db, PGSQL_ERRORS_VERBOSE);
### Emtpy DB
$result = pg_query("TRUNCATE TABLE My_DB_Name");
$fcontents = file ('///Library/FileMaker' Server/Data/Documents/EXPORT/export_file.tab');
  for($i=0; $i<sizeof($fcontents); $i++) {
      $line = trim($fcontents[$i]);
      $arr = explode("'t", $line);
      $query = "insert into My_DB_Name(
field1, field2 etc....      )
        values (
'{$arr[0]}','{$arr[1]}','{$arr[2]}','{$arr[3]}', etc........
        )";
      $result = pg_query($query); echo "'n Lines:".$i;
 pg_send_query($db, $query);
 $res1 = pg_get_result($db);
}
## Update geometry column
$sql = pg_query("
update darwincore2 set punkt_geom=
ST_SetSRID(ST_MakePoint(My_DB_Name.longitude, darwincore2.latitude),4326);
");

?>

我认为问题是您正在使用 file() 函数,该函数一次读取内存中的整个文件。尝试使用 fopen 和 fgets 逐行阅读。

$fp = fopen(filename, "r");
while (($line = fgets($fp)) !== false) {
    ... insert $line into the db....
}
fclose($fp);

您也可以使用 COPY 命令直接导入文件 (http://www.postgresql.org/docs/9.2/static/sql-copy.html)

这种情况可能发生在代码中,例如无限循环,处理大量数据,甚至数据库查询您应该检查代码,可能存在无限循环或此类情况