一時的なゴミは収集されますか?


61

この質問により、wp_optionsの一時的なRSSフィードは自動的に削除されないと考えました

一時的なものは期限が切れて削除されることになっています。ただし、これが処理されるのを確認する唯一の方法は、transientの有効期限が切れてリクエストされ、その後リクエスト中に削除される場合です。

トランジェントが期限切れになったがその後リクエストされなかった場合はどうなりますか?Codexの説明から、ある種のガベージコレクションが暗示されていると思いました。今、私は確信が持てず、そのようなコードを見つけることができません。

それで、それはデータベースに永久に残るでしょうか?


理論的には、cronの実行時に削除する必要があります(期限切れの場合)
onetrickpony

1
@Ambitious Amoebaええ、私はちょっとそれを問題に言及しました。私のポイントは-一時的な作成は、それが要求されることを想定または保証するものではありません。元の質問を強調- 私は決してならば期限切れ過渡が削除されるときと場合を取得しないことを?
11

1
期限切れのデータをクリーンアップすることを前提としていますが、そうです、削除されないことがある状況があります。トランジェントを使用するウィジェットを削除するようなものです。このために
トラックで

1
@Rarst-パッチを作成してtracに送信するのに最適なように聞こえますか?
-MikeSchinkel

回答:


45

彼らは今

WordPress 3.7から、データベースのアップグレード時に期限切れのトランジェントが削除されます。#20316を参照してください


古い答え

誰かが私を見せてくれないなら、トランジェントは結局ガベージコレクションされていないようです。さらに悪いことに、オプションとは異なり、データベースに保存されることが保証されていないということです。そのため、すべてのトランジェントのリストをフェッチして有効期限をチェックする信頼できる方法はありません。

データベースがストレージに使用されている場合、ガベージコレクションを行うためのいくつかの一時的なコード:

add_action( 'wp_scheduled_delete', 'delete_expired_db_transients' );

function delete_expired_db_transients() {

    global $wpdb, $_wp_using_ext_object_cache;

    if( $_wp_using_ext_object_cache )
        return;

    $time = isset ( $_SERVER['REQUEST_TIME'] ) ? (int)$_SERVER['REQUEST_TIME'] : time() ;
    $expired = $wpdb->get_col( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout%' AND option_value < {$time};" );

    foreach( $expired as $transient ) {

        $key = str_replace('_transient_timeout_', '', $transient);
        delete_transient($key);
    }
}

$ time = $ _SERVER ['REQUEST_TIME']; そして、SQLクエリで$ timeを使用します-それをしないでください。SQLインジェクションを防ぐために、$ _ SERVER変数/値をより慎重に処理してください。
-hakre

@hakre hm ... PHPのパフォーマンスに関するプレゼンテーションからtime()、バグを引き起こす可能性のある使用を推奨しています(実行は本質的に即座ではありません)。要求時間はPHP自体によって設定されており、ユーザーが指定したデータからは発生しません。この脆弱性はなぜですか?
11年

@Rarst:使用すべきではないとは言いませんでした。SQLクエリ内で使用できるように安全にエンコードされていることを確認してください。外部ソースからのすべての変数でこれを行う必要があります。$ _SERVER変数は期待どおりに設定されず、代わりに要求元のユーザーによっても設定される場合があります。いくつかの優れたコーディングプラクティスを広めたかっただけです。いつものように、可用性の実際の状態について学ぶには、ドキュメントを参照してください。- PHP 4については、例えば、そのような変数が存在し、カスタムヘッダまたは環境変数によって上書きされる可能性がないphp.net/manual/en/reserved.variables.server.php
hakre

@hakre修正(思う)、PHP4のリマインダーに感謝(WordPressがサポートを終了するのを待つことができません)
Rarst

それは私の目にはずっと良く見える;)。time()と負の整数には問題なく、トランジェントをすべて削除するか、まったく削除しない可能性があることを期待しましょう。実行中のシステムを信頼しないでください:P
hakre

20

コメントの一部をディスカッションから回答に移動し、言い回しや書式を変更します。

基本的には、極端なケースがない限り、「ガベージコレクト」する必要はないということです。それらを取得しない場合、それらが存在するかどうかは関係ありません。

トランジェントはデフォルトでオプションテーブルに保存されます。基本インストールでは、オプションテーブルにはおそらく100のエントリがあります。各トランジェントはさらに2つのエントリを追加しますが、たとえ数千個ある場合でも、それらは自動ロードされないため、サイトの速度には影響しません。

起動時に、WordPressはオプションをメモリに読み込みますが、自動読み込みフラグがオンになっているオプションのみを読み込みます。トランジェントはこれを取得しないため、メモリにロードされません。後で実際に使用されるトランジェントのみにコストがかかります。

データベースの観点から、オプションテーブルにはオプションIDとオプション名の両方のインデックスがあります。トランジェントは常に名前(キー)に基づいてロードされるため、それらのルックアップは常に単一の一意のキー値に対する単純な選択です。したがって、ルックアップはO(log(n))であり、非常に高速です。log(n)のBig-Oでは、気付く前に数百万行に達する必要があります。率直に言って、実際のデータ転送に加えて、クエリのセットアップと分解のオーバーヘッドははるかに長くなります。クエリ自体は、比較すると本質的にゼロ時間で実行されます。したがって余分な未使用の行追加しても、余分なディスク領域を使用する以外は何も影響しません。

データベースでのインデックス作成は、舞台裏で何が起こっているのか実際に理解していない人には意味のない、深く読まれたアイデアの1つです。データベースは、ゼロから高速にデータを取得できるように設計されており、この種の問題を問題なく処理できます。これはかなり良い読み物です:http : //en.wikipedia.org/wiki/Index_(database

現在、最も明白な方法(SQL DELETEを呼び出す)でのクリーンアップは、データベースから実際には削除しません。インデックスからそれらを削除し、行を「削除済み」としてマークします。繰り返しますが、これはデータベースの動作方法です。実際にディスク領域を空けるには、続けてOPTIMIZE TABLEを実行する必要がありますが、これは高速な操作ではありません。時間がかかる。おそらくそれ以上の時間です。合計でCPU時間を節約するには、おそらく十分ではありません。

使用されていない新しいトランジェントが継続的に挿入される原因となっている場合は、代わりに根本的な問題を見つける必要があります。これらのトランジェントを挿入するのは何ですか?彼らは、変更または変更キーを使用していますか?その場合、これを引き起こすプラグインまたはコードは、基本的には修正しないでください。それらを適切に作成していないコードもそれらを取得していないため、必要以上の作業を行っている可能性が高いため、これはより便利です。

一方、あらゆる投稿のようなものに対してトランジェントが作成される場合があります。これは確かに完全に受け入れられるかもしれません。Facebookからの受信コメントを保存するために、SFCで自分でこれを行います。各投稿には、関連する潜在的なトランジェントがあります。つまり、投稿ごとに2行余分になります。1万件の投稿がある場合、オプションテーブルには2万行あります(最終的に)。これは悪くも遅くもありません。データベースが本当に重要である限り、100行と20,000行の間にはほとんど差がないからです。すべてインデックス化されています。とても速いです。サブサブミリ秒。

あなたが何百万もの行に入り始めたら、私は心配するでしょう。オプションテーブルのサイズが数百メガバイトを超えて大きくなった場合は、詳しく調べるのに十分な心配があります。しかし、一般的に言えば、これは極端な場合を除いて問題ではありません。数十万の投稿がある大規模なニュースサイトのような小さなものにとっては、それは確かに問題ではありません。そして、それが問題となるのに十分な大きさのサイトでは、何らかの外部オブジェクトキャッシュを使用する必要があります。その場合、トランジェントはデータベースではなく自動的にそこに保存されます。


1
注意:有効期限のないトランジェントは自動的にロードされ、有効期限はデフォルトではないため、アプリケーション/プラグインが多くのトランジェントを作成し、有効期限を設定しない場合、ページ/ロード後のすべてのメモリでチャンクを使用します。
ウェブウェア

基本的に通常の「オプション」と同じであるため、「無期限の一時的」を使用する理由はありません。
オットー

1
確かに、それはデフォルトです。そのため、多くのプラグイン作成者が期限切れのないトランジェントを追加しています。
Webaware

1
さて、ここでの解決策は簡単です。これらのプラグインを使用しないでください。彼らは間違っています。トランジェントはセッションとして使用されるべきではありません。意味のある有効期限なしにトランジェントを使用しないでください。また、キーを変更または変更することはできません。
オットー

2
言って、7日間。プラグイン/テーマの作成者がより大きなまたはより小さなものを望んでいる場合、彼らはそれを指定します。自動ロードが必要な場合、有効期限(=無限)に0を指定する必要はありませんが、yes / no自動ロードパラメーターとして有効期限パラメーターが2重になっている現在の状況です。いずれにせよ、デフォルトの有効期限は、デフォルトとしてautoload = yesにつながるべきではありません。それは単にトラブルを求めているだけです。
Webaware

18

オットー-これ以上あなたに反対することはできませんでした。問題は、最終的にこれらすべてのトランジェントで、テーブルのサイズがばかげてしまうことです。行き詰まるのに何百万行もかかりません。現在、130k行を超えるオプションテーブルを扱っており、定期的にハングします。値フィールドは大きなテキストタイプであるため、「autoload」行のみを検索することもパフォーマンスの悪夢になります。これらの値フィールドは、残りの行データとは別に保存されます。論理的には同じテーブルの一部ですが、必要な行をプルアップするには結合が必要です。必要なデータがディスク上のいたるところに分散しているため、結合に時間がかかります。プロファイリング(mysqlのjetプロファイラーを使用)はこれを証明しています。

クラスタ化されたキーに自動ロードを追加すると、この問題の解決に役立つ場合があります。Autoload Descのクラスタリング(ID ASCなど)では、すべての自動ロード行が最初にディスク上でまとめられます。それでも、あなたはDBの観点から大きな負担を見ていると思います。

個人的には、このシステムの設計はおかしいと思います。オプション表は、多くの点で一般的なキャッチオールになっているようです。値フィールドが残りの行データと同じページに含まれるほど小さく、効果的にインデックス付けできる場合は、これで問題ありません。残念ながら、そうではありません。これを設計した人は誰でもDB101クラスに戻る必要があります。


5
本当ですが、WordPressの開発が始まったときに、データストレージとしてオプションテーブルを使用する数千のプラグインがあるとは誰も考えていなかったと考えてください:)
onetrickpony

@onetrickponyだから、いつか巨大になると思っても、常に時間をかけて正しいことをすることが重要です:)
Mahmoud Al-Qudsi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.