2


0

php、mysql、私のメモリリーク

このスクリプト(使い捨て)が漏れるとは思っていませんでしたし、犯人が何であるかを理解していません。 何か見つけられますか? これは使い捨てのコードですが、今後もこれを繰り返すのではないかと心配しています。 PHPでメモリを管理する必要はありませんでしたが、dbの行数により、phpインスタンスが爆破されています(すでにメモリを1Gbに増やしています)。

カリフォルニアのテーブルは、他のテーブルよりも特に大きくなっています(現在は2.2m行、重複する行を削除するほど少なくなっています)。 31行目でメモリエラーが発生しました($ row = mysql_fetch_assoc($ res))

_ 致命的なエラー:31行目のC:\ Documents and Settings \ R \ My Documents \ My Webpages \ cdiac \ cdiac dup.phpで1073741824バイトのメモリサイズを使い果たしました(24バイトを割り当てようとしました)。 __

PHP 5.3.0、mysql 5.1.36。 沼インストールの一部。

これがコード全体です。 このスクリプトの目的は、重複エントリを削除することです(データはセグメント化されたテーブルに取得されたため、当時ははるかに高速でしたが、これらのテーブルをマージする必要があります)。

何が原因ですか? 私が見落としているものは? または、メモリサイズを監視し、ガベージコレクションが大きくなったら手動で呼び出す必要がありますか?

 5) exit(0);
  }
  else {
    $last = $current;
    unset($prev_row);
    //copy $row to $prev_row
    foreach ($row as $key => $val) $prev_row[$key] = $val;
  }

  $i++;
}

    echo "\n\nDONE\n";
?>

3 Answer


2


私は二つのことを試みるでしょう:

1)ループ内で「mysql_query」を使用してUPDATEおよびDELETEクエリを実行する代わりに、後で実行するためにテキストファイルに保存します。 例: file_put_contents( 'queries.sql'、$ update、FILE_APPEND);

2) `while($ row = mysql_fetch_assoc($ res))`ループ内ですべてを行う代わりに、最初にすべてのSELECTクエリ結果を取得し、次にデータベース接続を閉じて、クエリ結果を含むすべてのデータベースリソースを解放します。 この後のみ、ループプロセスを実行します。

データベースの結果を1つの配列に保存しているときにメモリが不足した場合は、代わりに一時ファイルに結果を保存して(行ごとに1レコード/ FILE_APPEND)、ループでこのファイルを使用できます(レコードごとに1行を読み取り、 「fgets」関数を使用して)。


2


難なく終わらせた:

SELECT station_id, year, month FROM table
    GROUP BY station_id, year, month
    HAVING COUNT(*) > 1

これにより、テーブルに複数回出現するすべてのstation_id / year / monthタプルが取得されます。 ほとんどのデータが重複していないと仮定すると、多くのメモリを節約できます。これは、これらのタプルを調べて、一致する行を修正するだけで済むためです。


0


私のスクリプトでメモリ使用の問題を追跡しようとしたときにこれを見つけました。 私の問題を解決したので、同じ問題を抱えている次の人のためにここに返信を追加する価値があると思いました。

私はmysqliを使用していましたが、mysqlにもほぼ同じことが当てはまります。

私が見つけた問題は、クエリが結果を解放しないことでした。 解決策は、更新および削除クエリを実行した後にmysqli_free_result()を使用することでした。 しかし、より重要なことは、ループのmysqli_queryで* MYSQLI_USE_RESULT *の追加パラメーターを使用したことです。 これには副作用があるため、更新クエリと削除クエリには個別の接続を使用してください。