WordPress プラグインの Broken Link Checker を 2.4.9 にアップデートすると、503 エラーで落ちる・異常に重くなる——という投稿が X に流れていました。実際にインストールして試したところ、更新処理の「順序」のバグであることが分かりました。
しかも、バグは 2 つ混在していて、結果としてパッチが 2 日連続でリリースされていました。
この記事は、手元の docker で再現して、配布された 4 バージョン分(2.4.8〜2.4.11)の zip を AI に読み比べてもらって分かったことの共有です。先にまとめだけ置いておきます。
- 2.4.9 の DB スキーマ更新に順序バグがあり、リンクデータを持つ既存サイトでは必ず失敗する
- 失敗した更新は全リクエストで再試行される。これがサーバーを食い潰し、503 に至る
- 2.4.10 が DB バグの修正。2.4.11 は別のバグ(管理画面に入れなくなる Fatal)の修正
- 実測では、最新版への更新後最初の 1 リクエストでループは止まった
まず再現した
環境は docker(mysql:8.0 + wordpress:latest)。2.4.8 を入れて wp_blc_links に 502 行(うち同一 URL 2 行)を仕込み、プラグインのファイルを 2.4.9 に差し替えて自動更新を模擬しました。フロントページに curl を打つと、debug.log がこうなります。
[07-Aug-2026 23:27:40 UTC] WordPress database error Duplicate entry '' for key 'wp_blc_links.url_hash' for query ALTER TABLE `wp_blc_links` ADD UNIQUE KEY `url_hash` (`url_hash`) made by require('wp-blog-header.php'), ..., do_action('init'), blc_init, blcDatabaseUpgrader::upgrade_database, blcDatabaseUpgrader::make_schema_current, blcTableDelta::delta

リクエスト 5 回で、エラーがきっかり 5 行。1 リクエスト = 1 失敗 ALTER の綺麗な比例です。応答時間は正常時 35ms 前後だったのが、差し替え直後から 110〜250ms。リンク 502 行の小さなテーブルでこれなので、数万行を積んだ実サイトでは 1 回あたりのコストがさらに効きます。
失敗した更新は完了扱いにならないため、ページが表示されるたびに同じ失敗をやり直します。アクセスの数だけ失敗した DB 操作が積み上がってデータベースの処理枠を食い潰し、レンタルサーバーのリソース制限が発動して 503——という流れです。wp.org のフォーラムには共有サーバーの管理者から「サーバー全体で障害が繰り返し起きた」という報告があり、php-fpm のタイムアウトまで追い込まれて自力で復旧されている方もいました。
コードを読んだら順序バグだった
僕はプラグインのソースを深追いして、原因を突き止められるスキルはないので 2.4.8 と 2.4.9 の公式 zip を並べて、AI に diff を読ませました。原因は、テーブル定義に同時に追加されたこの 2 行に絞れました。
`url_hash` CHAR(32) NOT NULL DEFAULT '',
UNIQUE KEY `url_hash` (`url_hash`)
さらに、設計を読み解くと、意図はおそらく、① url_hash 列を追加 → ② 既存行に URL のハッシュ値を埋める → ③ 重複禁止の索引(UNIQUE KEY)を張る、の 3 段です。ところが実装では ① と ③ が同時に実行され、② はその後ろに置かれていました。既存行が全部 ''(空文字)のまま ③ が走る——そう、リンクが 2 行以上あるサイトでは 100% 失敗します。
新規インストールは行がゼロなので何も起きません。既存データを持った本番サイトでだけ発火する、テストをすり抜けやすい形をしています。ちなみに 2.4.9 の changelog でこの変更に対応するのは「Optimized BLC Local database」の 1 行だけでした。
2 日連続パッチの正体は、別々のバグの修正だった
ちなみに、2.4.10 と 2.4.11 が 2 日連続で出ていましたが、
- 2.4.10 が、今回の DB ループ(順序バグ)の修正
- 2.4.11 は別のバグの修正。設定によっては Fatal Error で管理画面に入れなくなるもので、フォーラムに複数あった「2.4.10 にしたら wp-admin に入れない」報告の正体はこちらでした
と、内容は別々。つまり 2.4.9 にはバグが 2 つ含まれていたようです。
| 日付(頃) | バージョン | 内容 |
|---|---|---|
| 8/5 | 2.4.9 | 問題の更新が配信される |
| 8/6 | 2.4.10 | DB 更新の無限リトライを修正 |
| 8/7 | 2.4.11 | 管理画面に入れなくなる Fatal を修正 |
最新版に差し替えたら、1 リクエストで止まった
壊れた状態から 2.4.11 に差し替えて、最初の 1 リクエストでこうなりました。既存行へのハッシュ値の埋め込みが完走 → 本物の重複 URL で索引の追加だけ 1 回失敗 → 記録して先へ進み、更新が完了扱いに。以後エラーはゼロで、応答時間も 35ms に戻りました。
なので、更新後のログに 1 回だけこういう行が残るのは正常系です。
Duplicate entry '92bfe7d12df995338195091fd06233ff' for key 'wp_blc_links.url_hash'
空文字 '' ではなく 32 桁のハッシュになっているのが見分けどころ。増え続けていたら異常、1 回だけなら完了しています。
対処としてやることは、実質 1 つで、最新版(2.4.11 以降)への更新です。管理画面が重すぎて開けない場合は、FTP かファイルマネージャーで wp-content/plugins/broken-link-checker をリネームすると WordPress がプラグインを自動で無効化するので、サイトが軽くなってから最新版を入れ直せば復帰できます。
おまけ: 自分たちの検査は、これを素通ししていた
僕らは、WordPress の更新を検証環境で試してから本番に当てるサービス(パッチオン)を作っています。せっかくなので、今回の 2.4.8 → 2.4.9 をその検査に通してみました。

結果は「安全」。そのまま本番に適用されました。
理由ははっきりしていて、この事故は画面が壊れないからです。ページは 200 で返るし、見た目も変わらない。更新の前後でスクリーンショットを比べる検査では、差分がまったく出ません。壊れているのはログの中だけでした。
そこで、検証環境の更新後に出るデータベースのエラーを判定材料に足して、同じ更新をもう一度通しました。

今度は「失敗」と判定して、本番への適用を見送りました。表示に出ない壊れ方は、表示を見る検査では捕まらない——という、当たり前を 1 つ塞いだ話でした。
追記欄
- 2026-08-08(公開時点): 2.4.11 リリース後の収束状況はフォーラム上でまだ確認しきれていません。続報があればここに追記します。
- 2026-08-09: 壊れた状態の再現環境で妙な差が出ました。同じ初期状態からリクエストを 1 本ずつ投げると 1 回目で更新が完了して直るのに、同時に 12 本投げると 6 本がエラーになって直りません。更新処理が並行して走ると、先に成功した 1 本以外は「もう索引がある」と言われて失敗し、失敗したリクエストは更新を完了扱いにしないまま終わるためのようです。アクセスの少ないサイトほど自然に直りやすく、アクセスの多いサイトほど抜け出せない、という非対称がありそうです。