タグアーカイブ バッチ処理

大規模WordPressサイトでプラグインが途中で止まるエラーの解決法

大規模WordPressサイトでプラグインが途中で止まるエラーの解決法

大規模なWordPressサイトでプラグインの一括処理が「0/」と表示されたまま進まず「error-generation stopped」で停止する現象は、PHPの実行時間やメモリ制限が主な原因だ。設定を調整しバッチサイズを小さくすれば、処理を最後まで走らせられる。

大規模サイトでプラグインが途中で止まる原因

大規模サイトでプラグインが途中で止まる原因

WordPressの管理画面から実行するプラグインの一括処理は、Webサーバーを介したHTTPリクエストのなかで動く。このリクエストにはサーバー側で複数の時間制限がかかっており、処理がそれを超えると強制終了する仕組みだ。

とくに影響が大きいのは以下の3つだ。

  • PHPの最大実行時間(max_execution_time)
  • PHPのメモリ制限(memory_limit)
  • WebサーバーやFastCGIのリクエストタイムアウト

5000件を超える投稿があるような大規模サイトでは、1回のリクエストですべてのデータを処理しようとすると、これらの制限に引っかかる。結果として「0/」のまま進捗が表示されず、しばらくしてエラー停止する。

プラグインのバッチ処理設定を見直す

プラグインのバッチ処理設定を見直す

最初に確認すべきは、そのプラグインがもつ「一度に処理する件数」の設定だ。多くの一括処理系プラグインは、内部的にデータを小分けにして処理するバッチサイズを指定できる。

プラグインの設定画面を開き、「1回あたりの処理件数」や「Records per iteration」といった項目を探す。デフォルトでは無制限に近い値になっていることも多く、これを10件〜50件程度まで下げるだけでエラーが解消するケースは多い。

バッチサイズを小さくすると処理全体の回数は増えるが、1回あたりの負荷が下がるためPHPやサーバーの制限にかかりにくくなる。この調整だけで問題が解決するなら、最も手軽でリスクの低い対処法だ。

Before(エラー発生)

一括処理を開始する

STEP 1 投稿データを読み込み中 (0/、)
⚠ 数秒後に「error-generation stopped」で停止
After(設定調整後)

バッチサイズを小さくして再試行する

STEP 1 少量ずつ確実に処理 (20/134)
✅ 最後まで完了
Before  After

上の図は、バッチサイズを調整するだけで一括処理が正常に完了する流れを表している。

PHPの最大実行時間とメモリ制限を引き上げる

PHPの最大実行時間とメモリ制限を引き上げる

バッチサイズの調整だけでは改善しない場合、PHP側の制限値が厳しすぎる可能性が高い。とくにレンタルサーバーの共用プランでは、max_execution_time が30秒、memory_limit が128MB程度に設定されていることが多い。

まず wp-config.php に以下の行を追加して制限を緩和する。

set_time_limit(300);
define('WP_MEMORY_LIMIT', '256M');

set_time_limit(300) はPHPの最大実行時間を300秒に延長し、WP_MEMORY_LIMIT はWordPressが利用できるメモリ上限を256MBに引き上げる。必要に応じて値をさらに増やしても構わない。

サーバー環境によっては、php.ini や .user.ini で直接 max_execution_time と memory_limit を指定できる場合もある。どちらの方法が有効かはサーバー仕様に依存するため、変更後は必ず phpinfo() やサイトヘルス画面で反映を確認する。

また、管理画面からの実行に限らず、サーバー負荷の高い処理ではメモリが不足しがちだ。256MBでも足りないようであれば512MBまで引き上げることを検討する。

サーバー側のリクエストタイムアウトを確認する

サーバー側のリクエストタイムアウトを確認する

PHPの実行時間を延ばしてもエラーが続くなら、WebサーバーやFastCGIのリクエストタイムアウトが原因だ。Apacheのmod_fcgidを使っている環境では、FcgidIOTimeout や FcgidBusyTimeout が短く設定されていると、PHPが処理中でも接続を切られてしまう。

この設定はサーバー全体に影響するため、共用サーバーではユーザー側で変更できないケースがほとんどだ。該当しそうな場合はサーバー管理会社のサポートに「管理画面の長時間処理が途中で切れる」と伝え、設定の緩和が可能か問い合わせる。

VPSや専用サーバーを利用しているなら、ApacheやNginxの設定ファイルでタイムアウト値を直接編集できる。変更後はWebサーバーの再起動を忘れずに行う。

WP-CLIでバックグラウンド処理を実行する

WP-CLIでバックグラウンド処理を実行する

サーバーがWP-CLIに対応しているなら、ブラウザからのHTTPリクエストではなくコマンドラインからプラグインの処理を走らせるのが最も確実な回避策だ。CLI実行にはWebサーバーのタイムアウト制限が適用されないため、大規模データでも安全に処理できる。

ただし、すべてのプラグインがWP-CLIコマンドを提供しているわけではない。まずプラグインの公式ドキュメントで「WP-CLI commands」の有無を確認し、該当するコマンドがあればターミナルから実行する。

実行例は以下のような形だ。

wp plugin-command run --batch-size=20

WP-CLIが使えない場合は、処理を手動で分割してブラウザから複数回に分けて実行する方法も有効だ。たとえばカテゴリ別や投稿タイプ別に絞り込み、1回の処理対象を数百件以下に抑える。

STEP 1 バッチサイズを10〜50件に下げる
STEP 2 PHPの実行時間とメモリ制限を引き上げる
STEP 3 サーバーやFastCGIのタイムアウトを緩和する
STEP 4 可能ならWP-CLIで実行する

これらの手順を順に試すことで、多くの大規模サイトで発生するタイムアウトエラーは解決できる。

よくある質問

共有サーバーでもPHPの最大実行時間は変更できるか

wp-config.php での set_time_limit() や .user.ini による上書きが許可されていれば可能だ。ただしサーバー側で一律に上限が決められており、設定値を超えて延長できない場合もある。

バッチサイズを小さくしても途中で止まる場合はどうすればよいか

メモリ制限と最大実行時間の両方を引き上げた上で、さらにバッチサイズを絞る。それでも改善しない場合は、サーバー側のリクエストタイムアウトが原因の可能性が高いため、サポートへの問い合わせやWP-CLIの利用を検討する。

「error-generation stopped」以外のエラーが表示されることはあるか

「このサイトで重大なエラーが発生しました」というWordPressの標準エラー画面や、「504 Gateway Timeout」といったサーバーエラーが表示されることもある。いずれも根本的な原因は処理時間の超過であることが多い。

特定のプラグインでしか発生しない場合はどう対処するか

まずそのプラグインの設定画面でバッチサイズを調整する。設定項目がなければ、開発元に問い合わせてフックやフィルターでバッチサイズを変更できないか確認する。別のプラグインで代替できる機能であれば、乗り換えも選択肢になる。

設定を変えてもまったく改善しない場合はサーバー移転が必要か

すべての設定を試しても解決しないなら、現在のサーバープランが大規模サイトの運用に適していない可能性が高い。VPSや専用サーバーなど、より自由度の高い環境への移行を検討するタイミングだ。

この記事のポイント

  • 大規模サイトの一括処理停止はPHPとサーバーの制限が原因
  • プラグインのバッチサイズを10〜50件に下げると効果的
  • max_execution_timeとmemory_limitの引き上げも併用する
  • 共用サーバーではサポートへの問い合わせが必要な場合もある
  • WP-CLIが使えれば最も確実に回避できる
WooCommerce HPOSが48時間で100万件以上のアクションスケジューラ完了ジョブを生成した原因と対処法

WooCommerce HPOSが48時間で100万件以上のアクションスケジューラ完了ジョブを生成した原因と対処法

WooCommerceサイトでデータベースサイズが突然急増し、wp_actionscheduler_actionsテーブルに数百万件もの完了済みジョブが蓄積している場合、HPOSデータ同期バッチプロセスが無限ループを起こしている可能性が極めて高い。ここでは症状の見分け方から原因の特定、停止、クリーンアップまで、具体的な手順をまとめる。

HPOS関連のデータベース肥大化が疑われる症状

HPOS関連のデータベース肥大化が疑われる症状

以下のような兆候が複数同時に現れたら、Action Schedulerの暴走を疑ってよい。

  • データベース容量が短時間で急激に増加する(数GB単位)
  • PHPエラーログのファイルサイズが異常に大きくなる
  • データベースのロックエラーやデッドロックが頻発する
  • 管理画面やフロントエンドで「INSERT command denied」などのエラーが出る
  • サーバーのバックグラウンドプロセスがほぼ常時稼働し続ける
  • 注文件数が数百件なのにAction Schedulerテーブルだけが肥大化している

これらの症状は、単体では他の原因もあり得るが、データベース内の完了ジョブが異常に増えている点が最大の特徴だ。

正常時(Before)
wp_actionscheduler_actions テーブルに数百件程度のジョブが存在する
暴走時(After)
100万件以上の完了ジョブが蓄積し、データベース全体が膨張する
正常時  暴走時

Action Schedulerが暴走していないか確認する方法

Action Schedulerが暴走していないか確認する方法

まずはデータベースを直接調べ、どのジョブが何件蓄積しているかを確かめる。WP-CLIが使えるならコマンドラインから、そうでなければphpMyAdminやAdminerで以下のクエリを実行する。

STEP 1 Action Schedulerテーブルの完了ジョブ数を集計する
STEP 2 フック名「wc_run_batch_process」でフィルタし、引数を確認する
STEP 3 注文件数とジョブ件数を比較し、異常な乖離を確認する
STEP 4 実行中のジョブが1件完了するたびに次が即座にスケジュールされるループを特定する

完了ジョブの数とフック名を調べる

データベースに直接問い合わせる場合、以下のSQLで完了状態のジョブをフック名別に集計できる。

SELECT hook, COUNT(*) AS cnt
FROM wp_actionscheduler_actions
WHERE status = 'complete'
GROUP BY hook
ORDER BY cnt DESC
LIMIT 10;

ここで wc_run_batch_process の件数が数十万〜数百万件と突出していれば、疑いは濃厚だ。

引数(args)から発行元を特定する

次に、そのフックの引数を見る。例えば以下のクエリで先頭の数件を取得する。

SELECT action_id, args, scheduled_date_gmt
FROM wp_actionscheduler_actions
WHERE hook = 'wc_run_batch_process'
AND status = 'complete'
ORDER BY action_id DESC
LIMIT 5;

引数フィールドにはシリアライズされたデータが入っている。その中に Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer という文字列が含まれていれば、HPOSのデータ同期機構がバッチを発行している証拠だ。

注文件数との比較で異常を確信する

管理画面のWooCommerce → 注文で表示される注文の総数は、データベースの wp_posts(またはHPOS有効時は wp_wc_orders)で確認できる。注文が600件しかないのに、同期バッチの完了ジョブが100万件もあるなら、明らかにループが発生している。

動作中のループをリアルタイムで観察する

WP-CLIが利用可能なら、以下のコマンドでペンディング状態のジョブを監視する。

wp action-scheduler list --hook=wc_run_batch_process --status=pending

定期的に実行すると、常に1件だけ存在し、それが完了するとすぐに新たなペンディングが生まれるパターンが観測できるはずだ。これはキューが滞留しているのではなく、バッチ自身が次をスケジュールし続ける無限ループであることを示す。

なぜHPOS DataSynchronizerが無限ループを起こすのか

なぜHPOS DataSynchronizerが無限ループを起こすのか

HPOS(High-Performance Order Storage)を有効にすると、WooCommerceは注文データを従来の wp_posts テーブルから専用テーブルへ移行する。この移行やデータの同期を担うのが DataSynchronizer であり、バックグラウンドでバッチ処理を走らせる。

通常は同期が完了すればバッチは停止するが、何らかの設定不整合やエラーにより「同期が完了したと見なされず、次のバッチが即座に予約される」状態に陥ることがある。具体的には、各バッチが「保留中 → 完了 → 次バッチ予約」というサイクルを際限なく繰り返す。注文数が少なくても、このループによってAction Schedulerのテーブルだけが急激に肥大化し、データベース全体を圧迫する。

保留中(Pending)
完了(Complete)
次バッチ予約(Schedule Next)
再び 保留中(Pending)へ
↑ 無限にループする

このループが起きているかどうかは、データベースを直接見るまで気づきにくい。キャッシュやRedis、WP Rocketなどを最初に疑いがちだが、真因はAction Schedulerの中にある。

データベースの安静化とクリーンアップの手順

データベースの安静化とクリーンアップの手順

原因がHPOSの同期バッチループと判明したら、ループを止め、完了ジョブを削除し、再発を防ぐ。以下の手順を順に実行する。

STEP 1 WP-CLIで同期状態を確認し、必要に応じて同期をリセットする
STEP 2 Action Schedulerの完了ジョブを安全に一括削除する
STEP 3 データベーステーブルを最適化し、容量を解放する
STEP 4 再発防止のためにHPOS設定を見直す

同期状態のリセット

まず、現在のHPOS同期状況を確認する。WP-CLIで次のコマンドを実行する。

wp wc hpos sync status

ここで「status: in-progress」や「pending」が表示される場合、同期が完了しておらず、バッチが動き続けている可能性がある。強制的にリセットし、不要な同期を停止するには以下を実行する。

wp wc hpos sync reset

リセット後、再度ステータスを確認し「idle」や「complete」になっていれば、新たなバッチはスケジュールされなくなる。

完了ジョブの一括削除

100万件単位の完了ジョブを削除するには、Action Schedulerが提供するWP-CLIコマンドを使うのが安全で高速だ。以下のコマンドで、完了状態のジョブをすべて削除できる。

wp action-scheduler clean --status=complete

特定のフックのみを削除したい場合は、プレーンなSQLで一度に削除してもよいが、必ず事前にデータベース全体のバックアップを取ること。

DELETE FROM wp_actionscheduler_actions
WHERE hook = 'wc_run_batch_process' AND status = 'complete';

さらに、関連するログテーブル(wp_actionscheduler_logs)の不要レコードも合わせて削除すると、ディスク容量を大きく回復できる。ただし、こちらは慎重に扱う必要があるため、まずは完了ジョブの削除だけでも効果は大きい。

テーブル最適化で容量を解放

大量のレコードを削除した後は、データベースが断片化し、実際の容量が解放されないことがある。phpMyAdminなどから該当テーブルに対して「最適化(OPTIMIZE TABLE)」を実行するか、以下のSQLを流す。

OPTIMIZE TABLE wp_actionscheduler_actions;
OPTIMIZE TABLE wp_actionscheduler_logs;

これにより、削除した領域がOSに返却され、データベース全体のサイズが縮小する。

再発防止とHPOS設定の見直し

ループが再発しないように、WooCommerceのHPOS設定を確認する。管理画面の WooCommerce → 設定 → 詳細設定 → 機能 から「High-performance order storage(高性能注文ストレージ)」が有効になっているか、そして「互換モードを有効にする」や「データ同期を有効にする」オプションがどのようになっているかをチェックする。

既に全注文がHPOSテーブルに完全移行済みで、互換モードが不要なら、これらの同期オプションを無効化することで、バックグラウンドのバッチ処理そのものを止められる。ただし、テーマやプラグインが古い注文データ参照方法を使っている場合は注意が必要だ。

また、WP-CLIのcronを定期的に監視し、Action Schedulerのジョブ数が異常増加していないかをチェックする仕組みをサーバー監視に組み込むと早期発見につながる。

よくある質問

HPOSが有効かどうかはどこで確認できるか

管理画面の「WooCommerce → 設定 → 詳細設定 → 機能」に移動し、「注文データストレージ」の項目で「High-performance order storage」が選択されていれば有効だ。WP-CLIでは wp wc hpos status で確認できる。

完了ジョブを削除してもサイト動作に影響はないか

Action Schedulerの完了ジョブは過去の処理履歴であり、削除しても現在予約されているジョブや進行中の処理には影響しない。ただし、監査やデバッグ目的で残したい場合は、削除前にバックアップを取ることを強く推奨する。

WP-CLIが使えないレンタルサーバーではどうすればよいか

phpMyAdminなどのデータベース管理ツールから直接SQLで削除できる。プラグイン「WP Crontrol」などを利用すれば、Action Schedulerの一覧を管理画面で確認し、フックごとに手動で削除することも可能だが、件数が多い場合はSQLのほうが現実的だ。

同期をリセットしてもループが再発するのはなぜか

根本原因が解消されていないと再発する。たとえば、同期オプションが有効なまま残っていたり、カスタムコードがバッチをトリガーし続けているケースがある。同期の完全停止を試み、プラグインの干渉も疑いながら一つずつ切り分ける必要がある。

この記事のポイント

  • データベースの急激な肥大化とAction Schedulerの完了ジョブ数に注目する
  • フック名「wc_run_batch_process」と引数からHPOSの同期バッチループを特定する
  • WP-CLIで同期状態をリセットし、完了ジョブを一括削除してテーブルを最適化する
  • HPOSの同期設定を見直し、不要なバッチ処理を完全に止めて再発を防ぐ