コンテンツへスキップ

WordPressのトランジェント(transient)APIの仕組みと、いつ wp transient delete が効くか

WordPressには「一定時間だけ保存して、期限が切れたら自動的に無効になるデータ」を扱う仕組みが標準で組み込まれている。トランジェント(transient)APIと呼ばれるこの機能は、外部APIの応答結果や重い計算処理の結果を一時的にキャッシュするためにコア機能やプラグインが広く使っている。便利な反面、仕組みを理解せずに使われると、期限切れのまま残り続けたデータがデータベースを圧迫する原因にもなる。

補足: トランジェントAPIは、WordPressコアが提供するPHP関数群(set_transient() / get_transient() / delete_transient())の総称。名前の由来は「transient(一時的な)」で、有効期限付きのキャッシュを簡単に扱うための仕組み。

トランジェントAPIの仕組み

トランジェントは、値・キー名・有効期限(秒数)の3つを指定して保存する。

set_transient('weather_data', $api_response, 3600); // 1時間だけ保存

保存先はサイトの構成によって変わる。

  • 標準構成(多くのレンタルサーバー環境): wp_optionsテーブルに_transient_<キー名>という行として保存され、有効期限は_transient_timeout_<キー名>という別の行に保存される
  • 永続オブジェクトキャッシュ導入時(RedisやMemcachedをバックエンドに使うプラグインを導入している場合): wp_optionsではなく、そちらのキャッシュ層に保存される

get_transient()を呼んだ時、WordPressは_transient_timeout_<キー名>の値と現在時刻を比較し、期限切れであればfalseを返す。この時点で該当行はコアの内部処理により削除されるのが本来の設計だが、この自動削除が確実に働くとは限らない。

なぜ期限切れのまま残り続けるのか

理屈の上では「期限が切れたら消える」はずのトランジェントが、wp_optionsに大量に残り続けるケースがある。主な原因は次の2つ。

  1. get_transient()が一度も呼ばれない: 前述の自動削除は「取得しようとしたら期限切れだったので削除する」という受動的な仕組みであり、能動的に古いレコードを掃除する処理ではない。プラグインが値をセットしたきり、その値を二度と取得しなければ、期限切れ後もレコードは残り続ける
  2. WP-Cronのガベージコレクションが走らない: WordPressコアにはwp_scheduled_deleteなど定期的に期限切れデータを掃除するcronジョブがあるが、WP-Cronはページアクセスに依存する疑似cronであるため、アクセスが極端に少ないサイトではこの掃除処理自体が長期間実行されない可能性がある

さらに厄介なのは、_transient_で始まるオプションの多くがautoload=yes(毎回のページ読み込み時に自動的にメモリへロードされる設定)で保存される点である。数十件程度なら影響は軽微だが、数千件規模まで蓄積すると、トランジェントの中身を一度も参照しないページでも、その全件が毎回読み込まれることになり、サイト全体の応答が緩やかに重くなっていく。

wp transient コマンドで状態を確認・整理する

WP-CLIには専用のサブコマンド群が用意されている。

# 現在保存されているトランジェント一覧を確認
wp transient list

# 特定のキーを個別削除
wp transient delete weather_data

# 期限切れのものだけをまとめて削除
wp transient delete --expired

# 期限に関わらず全件削除
wp transient delete --all

--expired--allの違いは重要である。--expiredは文字どおり期限切れのレコードだけを対象にするため、実行しても副作用はほぼない。一方--allは有効期限内の生きているキャッシュも含めて全部削除するため、実行直後は各プラグインが値を再計算・再取得する必要が生じ、外部APIへのアクセスが集中したり、一時的にページの応答が遅くなったりする可能性がある。原因調査でキャッシュを強制的にリセットしたい場合を除き、日常のメンテナンスでは--expiredを使うのが安全である。

補足: 永続オブジェクトキャッシュ(Redis/Memcached)を導入している環境では、wp transientコマンドがオブジェクトキャッシュ層を操作対象にする。この場合wp_optionsテーブルを直接確認しても実態と一致しないため、wp db query "SELECT COUNT(*) FROM wp_options WHERE option_name LIKE '_transient_%'"のような確認方法は、オブジェクトキャッシュ未導入の環境でのみ意味を持つ。

いつ実行するべきか

  • サイトの表示が全体的に重く感じる時の一次切り分けとして: wp option list --autoload=on --search='_transient_%'で件数を確認し、数千件規模に達していればwp transient delete --expiredを試す価値がある
  • プラグインの入れ替え・大量アンインストール後: 一部のプラグインは自身が使ったトランジェントをdelete_transient()で丁寧に片付けずにアンインストールされることがあり、使われなくなった_transient_行が孤立して残ることがある
  • 定期メンテナンスの一部として: wp db check / wp db optimizeと同じサイクルに組み込み、期限切れトランジェントの掃除を機械的な習慣にしておくと、autoloadオプションの肥大化を早期に発見しやすくなる

まとめ

したいこと コマンド
現在のトランジェント一覧を確認 wp transient list
特定のキーだけ削除 wp transient delete <キー名>
期限切れ分だけをまとめて削除(安全) wp transient delete --expired
全件削除(副作用あり・原因調査時のみ推奨) wp transient delete --all
autoloadオプションの肥大化を確認 wp option list --autoload=on --search='_transient_%'

トランジェントAPIは「一時的に保存して自動で消える」という前提で設計されているが、その前提が成り立つのはget_transient()が定期的に呼ばれ、かつWP-Cronのガベージコレクションが正常に機能している場合に限られる。データベースの健全性をwp db check/wp db optimizeで定期的に確認する運用に、トランジェントの棚卸しを組み込んでおくと、autoloadオプションの肥大化という見えにくい負債を早い段階で断つことができる。