問題描述

這個問題讓我想起 Transient RSS feeds in wp_options not removed automatically?

瞬變應該過期並被刪除。但是,我看到處理的唯一方法是暫時過期並被請求,然後在請求期間被刪除。

如果瞬時過期但從未請求過嗎?從食品法典的描述我認為某種垃圾收集是隱含的。現在我不太確定,找不到任何執行這樣的代碼。

那麼它會永遠被卡在數據庫中嗎?

最佳解決方案

他們現在是

從 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);
    }
}

次佳解決方案

通過 re-wording 和 re-formatting 將一些評論從討論中移到答案中。

基本上,它歸結到的是,除非你有一個超級極端的情況,他們真的不需要是”garbage collected” 。如果你從來沒有拿過他們,那麼無論他們在哪裏,都沒關係。

參見,默認情況下,瞬態存儲在選項表中。在基礎安裝中,選項表中可能有 100 個條目。每個臨時增加兩個條目,但是即使有數千個條目,它們也不會影響網站速度,因為它們不被自動加載。

在啓動時,WordPress 將選項加載到內存中,但它只加載其自動加載標誌已打開的選項。瞬態不能得到這個,所以不要加載到內存中。只有以後實際使用的瞬變才會產生成本。

從數據庫的角度來看,options 表具有選項 ID 和選項名稱的索引。瞬態總是基於名稱 (鍵) 加載,因此它們的查找始終是單個唯一鍵值上的簡單選擇。因此,查找是 O(log(n)),並且超快。使用日誌 (n) 的 Big-O,您必須進入數百萬和數百萬行才能變得顯而易見。坦率地説,查詢的設置和拆卸的開銷以及實際的數據傳輸更長。查詢本身通過比較基本上運行在 zero-time 中。所以只需要額外使用的行就不會影響任何東西,只能使用額外的磁盤空間。

數據庫中的索引是 deep-read 的一種想法,對於不瞭解幕後情況的人來説,這些想法是沒有意義的。數據庫設計用於快速數據檢索,從頭開始,可以處理這種事情沒有問題。這是一個很好的閲讀:http://en.wikipedia.org/wiki/Index_(database)

現在,以最明顯的方式 (調用 SQL DELETE) 清理它們並不會從數據庫中刪除它們。它只是從索引中刪除它們,並將該行標記為”deleted” 。再次,這只是數據庫的工作原理。要實際清除磁盤空間,您必須繼續,然後執行一個 OPTIMIZE TABLE,這不是一個快速的操作。這需要時間。可能更多的時間比它的價值。總共可以節省 CPU 時間,這可能還不夠。

如果您有某種情況導致連續插入未被使用的新瞬變,則需要找到基礎問題。什麼是插入這些瞬變?他們在使用更改或變更的密鑰嗎?如果是這樣,那麼導致這個的插件或代碼應該是固定的,基本上不這樣做。這將會更有幫助,因為沒有正確創建它們的代碼可能不是檢索它們,因此做的更多的工作。

另一方面,可能存在像每個帖子這樣的事物創建瞬變的情況。這可能是完全可以接受的。我自己在證監會做這個,以存儲來自 Facebook 的意見。每個帖子都有一個潛在的瞬態關聯,這意味着每個帖子有兩個額外的行。如果你有 10k 的帖子,那麼在選項表中最終會有 20k 行。這不錯還是緩慢,因為數據庫真的很在乎,100 行和 20,000 行之間的差別很小。這都是索引。它的速度很快。 Sub-sub-milliseconds 。

當你開始上百萬行時,我會擔心。當選項表的大小增加到數百兆字節以上時,我會很關心,仔細看看。但一般而言,除極端情況外,這不是一個問題。任何比像大型新聞網站那樣小的東西,數以萬計的帖子,這當然不是問題。而對於任何足夠大的網站來説,這是一個問題,您應該使用某種外部對象緩存,而在這種情況下,瞬態會自動存儲在數據庫中而不是數據庫中。

第三種解決方案

奧託 – 我不能不同意你的意見。問題是,最終所有這些瞬間,桌子的大小變得可笑。它不會使數百萬行陷入死鎖。我正在處理一個超過 130k 行的選項表,並定期掛起。因為值字段是一個大的文本類型,甚至只尋找”autoload” 行成為一個噩夢的表現。這些值字段與行數據的其餘部分分開存儲。即使它在邏輯上是同一個表的一部分,連接必須發生,以便拉出你想要的行。加入現在永遠是因為您需要的數據遍佈磁盤上的所有位置。 Profiling(使用 jet profiler for mysql) 證明瞭這一點。

將 auto-load 添加到羣集密鑰可能有助於解決此問題。自動加載描述中的集羣 (例如 ID ASC) 將允許所有自動加載行首先在磁盤上聚集在一起。即使我仍然認為你從數據庫的角度來看待一個巨大的壓力。

就個人而言,我認為這個系統的設計是一個很好的選擇。選項表似乎已經變成了一般的 catch-all 很多東西。如果值字段足夠小以便與 rowdata 的其餘部分包含在同一頁面上,那麼就可以了,並且可以有效地建立索引。不幸的是,情況並非如此。誰設計這個需要回到 DB101 課堂。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。