0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravelで本番DBを使用したらallowed memory size exhausted

Posted at

状況

laravelで作ったプロジェクトを本番DBを接続したら、以下のエラーが発生。

コマンドライン
Allowed memory size of 134217728 bytes exhausted (tried to allocate xxxxxxxx bytes)

試験環境のDBテーブルではレコードがせいぜい数百件しかなかったので何も問題が起きなかったが、本番DBテーブルでは数十万件のレコードがあった。
この状態で多対多リレーションを書き換えようとしたことが原因。

解決

はじめはphpのプロセスメモリ使用制限を設定しているシステム変数memory_limitで設定を変更した。

php.ini
memory_limit=2M
systemctl restart

しかし、これでもエラーが出続けた。

調べるとlaravelのEloquentにchunk(), chunkByID()、cursor()があり、今回はデータの更新だったのでchunkByID()を利用。
多対多リレーションで使用したテーブルはlettersとstampsだったので、中間DBテーブルをletter_stampで作成。

LetterController.php
$count = 0;
DB::table('letter_stamp')->where('active', true)
    ->chunkById(100, function ($pivots) {
        foreach ($pivots as $pivot) use($count) {
            $pivot->update(['stamp_id'], null);
            $count++;
        }
    });

中間テーブルのレコードを100件ずつ取得し、値の更新。
その際にクロージャへ親スコープから$count変数を引き継いで、更新件数を把握している。

おまけ

Laravel日本語版公式サイトによるとchunk()では

クロージャから falseを返えせば、それ以上のチャンクの処理を停止できます。

とのことなので、return falseで処理から抜けることができます。

参考資料

Laravel8.x 公式
チャンキングで使用メモリを抑える
LaravelでデータをDBに保存したいときのメモリ不足をなんとかする
Laravel で chunk を使いながらトータル件数を計算
Laravel(Eloquent): chunk() vs cursor()

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?