Czy przejściowe śmieci są zbierane?

61

To pytanie sprawiło, że pomyślałem, że przejściowe kanały RSS w wp_options nie są usuwane automatycznie?

Stany przejściowe mają wygasnąć i zostać usunięte. Jednak jedynym sposobem, w jaki widzę, że jest to obsługiwane, jest to, że transient wygasł i został zgłoszony, a następnie usunięty podczas żądania.

Co się stanie, jeśli stan przejściowy wygasł, ale po tym nigdy nie jest wymagany? Z opisu zawartego w Kodeksie pomyślałem, że implikuje się pewien rodzaj śmieci. Teraz nie jestem tego taki pewien i nie mogę znaleźć żadnego kodu, który by to wykonał.

Czy to po prostu utknie w bazie danych na zawsze?

Rarst
źródło
teoretycznie powinny zostać usunięte po uruchomieniu crona (jeśli wygasły)
onetrickpony
1
@Ambitious Amoeba tak, trochę wspomniałem o tym w pytaniu. Chodzi mi o to - przejściowe stworzenie nie zakłada ani nie gwarantuje, że kiedykolwiek będzie wymagane. Podkreślając pierwotne pytanie - kiedy i czy wygasł stan przejściowy zostanie usunięty, jeśli go nigdy nie otrzymam ?
Rarst
1
zakłada, że ​​usuwasz wygasłe dane, ale tak, masz rację, są sytuacje, w których nigdy nie zostaną usunięte. Jak usunięcie widżetu, który używa stanów nieustalonych. W tym celu należy przesłać bilet na
trasę
1
@Rarst - Brzmi jak idealna rzecz do napisania łatki i przesłania do trac?
MikeSchinkel
1
Powiązany trac bilet: core.trac.wordpress.org/ticket/20316
Stephen Harris

Odpowiedzi:

45

Teraz są

Począwszy od WordPress 3.7 wygasłe transjenty są usuwane podczas aktualizacji bazy danych, patrz # 20316


Stara odpowiedź

Jeśli ktoś nie może mi pokazać inaczej, wydaje się, że przejściowe nie są w końcu śmieciami. Co gorsza, w przeciwieństwie do opcji nie ma gwarancji, że będą przechowywane w bazie danych. Dlatego nie ma niezawodnego sposobu na pobranie listy wszystkich stanów nieustalonych w celu sprawdzenia ich ważności.

Niektóre prowizoryczne kody do czyszczenia pamięci, jeśli baza danych jest używana do przechowywania:

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);
    }
}
Rarst
źródło
$ time = $ _SERVER ['REQUEST_TIME']; a następnie wykorzystując $ time w zapytaniu SQL - nie rób tego. Postępuj ostrożniej ze zmiennymi / wartościami $ _SERVER, aby zapobiec wstrzyknięciom SQL.
hakre 10.01.11
@hakre hm ... Wybrałem to z prezentacji na temat wydajności PHP, która zaleciła to nad używaniem, time()co może powodować błędy (wykonanie z natury nie jest natychmiastowe). Czas żądania jest ustawiany przez sam PHP, nie pochodzi z żadnych danych dostarczanych przez użytkowników. Dlaczego ta luka?
Rarst 10.01.11
@Rarst: Nie powiedziałem, że nie powinieneś go używać, powinieneś tylko upewnić się, że jest bezpiecznie zakodowany do użycia wewnątrz zapytania SQL. Powinieneś to zrobić z każdą zmienną z zewnętrznego źródła. Zmienne $ _SERVER mogą nie być ustawione zgodnie z oczekiwaniami, a zamiast tego mogą zostać ustawione nawet przez żądającego użytkownika. Chciałem jedynie propagować dobre praktyki kodowania. Jak zawsze, aby dowiedzieć się o rzeczywistym stanie dostępności, zobacz dokumentację. Na przykład w PHP 4 taka zmienna nie istnieje i może zostać zastąpiona niestandardowym nagłówkiem lub zmienną środowiskową - php.net/manual/en/reserved.variables.server.php
hakre
@hakre naprawione (tak myślę), dzięki za przypomnienie PHP4 btw (nie mogę się doczekać, aż WordPress
zrezygnuje
W moich oczach wygląda to znacznie lepiej;). Miejmy nadzieję, że nie ma problemu z time () i ujemnymi liczbami całkowitymi, które mogłyby usunąć wszystkie transfery lub nie mieć żadnych stanów przejściowych niż przypadkowo. Nigdy nie ufaj działającemu systemowi: P
hakre
20

Przeniesienie niektórych komentarzy z dyskusji do odpowiedzi, z przeformułowaniem i przeformatowaniem.

Zasadniczo sprowadza się to do tego, że chyba, że ​​masz bardzo ekstremalny przypadek, tak naprawdę nie muszą być „śmieciami”. Jeśli nigdy ich nie przyniesiesz, nie ma znaczenia, czy są, czy nie.

Zobacz, transjenty są domyślnie przechowywane w tabeli opcji. W instalacji podstawowej w tabeli opcji może znajdować się może 100 pozycji. Każdy stan przejściowy dodaje dwa kolejne wpisy, ale nawet jeśli masz tysiące, nie wpływają one na szybkość witryny, ponieważ nie są ładowane automatycznie.

Podczas uruchamiania WordPress ładuje opcje do pamięci, ale ładuje tylko opcje z włączoną flagą automatycznego ładowania. Stany przejściowe tego nie dostają, więc nie ładuj się do pamięci. Tylko przejściowe, które zostaną faktycznie wykorzystane później, będą kosztować.

Z perspektywy bazy danych tabela opcji zawiera indeksy zarówno identyfikatora opcji, jak i nazwy opcji. Stany przejściowe są zawsze ładowane na podstawie nazwy (klucza), więc wyszukiwania dla nich zawsze są prostymi zaznaczeniami na podstawie jednej unikalnej wartości klucza. Zatem wyszukiwanie to O (log (n)) i jest super szybkie. Z Big-O log (n), będziesz musiał dostać się do milionów i milionów wierszy, zanim stanie się zauważalny. Szczerze mówiąc, narzut związany z konfiguracją i porzuceniem zapytania, wraz z faktycznym przesyłaniem danych, jest znacznie dłuższy. Dla porównania samo zapytanie działa zasadniczo w czasie zero. Po prostu posiadanie dodatkowych nieużywanych wierszy nie wpływa na nic poza wykorzystaniem dodatkowego miejsca na dysku.

Indeksowanie w bazach danych jest jednym z tych głęboko przeczytanych pomysłów, które nie mają sensu dla osób, które tak naprawdę nie zrozumiały, co dzieje się za kulisami. Bazy danych zostały zaprojektowane z myślą o szybkim wyszukiwaniu danych od podstaw i potrafią poradzić sobie z tego rodzaju sprawami bez problemów. To całkiem dobra lektura: http://en.wikipedia.org/wiki/Index_(database )

Teraz czyszczenie w najbardziej oczywisty sposób (wywoływanie na nich SQL DELETE) tak naprawdę nie usuwa ich z bazy danych. Po prostu usuwa je z indeksu i oznacza wiersz jako „usunięty”. Ponownie, tak właśnie działają bazy danych. Aby faktycznie wyczyścić miejsce na dysku, musisz kontynuować i wykonać OPTYMALIZACJĘ TABELI, a to nie jest szybka operacja. To wymaga czasu. Prawdopodobnie więcej czasu niż jest warte. Prawdopodobnie to nie wystarczy, aby dać ci oszczędność czasu procesora.

Jeśli masz jakiś przypadek, który powoduje ciągłe wstawianie nowych stanów przejściowych, które nie są używane, musisz zamiast tego znaleźć podstawowy problem. Co to jest wstawianie tych stanów przejściowych? Czy używają zmieniającego się lub mutującego klucza? Jeśli tak, to wtyczka lub kod powodujący to powinny zostać naprawione, aby w zasadzie tego nie robić. Będzie to bardziej pomocne, ponieważ jest prawdopodobne, że kod, który nie tworzy ich poprawnie, również ich nie pobiera, a tym samym wykonuje więcej pracy niż musi.

Z drugiej strony może zdarzyć się, że tworzone są transjenty dla czegoś takiego jak każdy post. To może być rzeczywiście do przyjęcia. Robię to sam w SFC, aby przechowywać komentarze przychodzące z Facebooka. Z każdym postem jest powiązany potencjalny stan przejściowy, co oznacza dwa dodatkowe rzędy na post. Jeśli masz 10 000 postów, będziesz mieć 20 000 wierszy w tabeli opcji (ostatecznie). Nie jest to ani złe, ani powolne, ponieważ znowu, pomiędzy bazami danych a 20 000 wierszy jest bardzo mała różnica, o ile bazy danych naprawdę dbają. Wszystko jest indeksowane. Jest szybki jak do cholery. Sub-pod-milisekundy.

Kiedy zaczniesz się układać w miliony rzędów, będę się martwić. Gdy rozmiar tabeli opcji wzrośnie powyżej setek megabajtów, byłbym wystarczająco zainteresowany, aby przyjrzeć się bliżej. Ale ogólnie rzecz biorąc, nie jest to problem, z wyjątkiem ekstremalnych przypadków. Z pewnością nie stanowi to problemu dla czegoś mniejszego niż coś takiego jak duży serwis informacyjny z setkami tysięcy postów. I dla każdej strony wystarczająco dużej, aby stanowiła to problem, powinieneś używać jakiegoś zewnętrznego bufora obiektów, aw takim przypadku transjenty są tam automatycznie zapisywane zamiast w bazie danych.

Otto
źródło
1
Uwaga: transjenty bez wygasania są automatycznie ładowane, a wygasanie nie jest ustawieniem domyślnym , więc tam, gdzie aplikacja / wtyczka tworzy wiele stanów nieustalonych i nie ustawia wygasania, będą używać kawałków pamięci na każdym ładowaniu strony / postu.
webaware
Nie ma powodu, aby używać „przejściowego bez wygaśnięcia”, ponieważ jest to w zasadzie identyczne z normalną „opcją”.
Otto,
1
Jasne, ale to domyślne . W związku z tym wielu autorów wtyczek dodaje przejściowe, które nie wygasają.
webaware
1
Cóż, rozwiązanie tutaj jest proste: nie używaj tych wtyczek. Robią to źle. Transjentów nie należy używać jako sesji, nie należy ich używać bez znaczącego wygaśnięcia i nie powinny one mieć mutujących ani zmieniających kluczy.
Otto
2
Powiedz 7 dni. Jeśli autor wtyczki / motywu chce czegoś większego lub mniejszego, to to określi. Jeśli chcą automatycznego ładowania, nie powinni musieli określać 0 dla ważności (= nieskończoność), ale właśnie to mają teraz, gdy parametr ważności działa podwójnie jako parametr automatycznego ładowania tak / nie. Tak czy inaczej, domyślne wygaśnięcie nie powinno również prowadzić do automatycznego ładowania = domyślnie; to tylko proszenie o kłopoty.
internetowa
18

Otto - Nie mogłem więcej się z tobą nie zgadzać. Problemem jest to, że ostatecznie przy tych wszystkich stanach przejściowych rozmiar stołu staje się śmieszny. Bagno nie zajmuje milionów wierszy. Obecnie mam do czynienia z tabelą opcji, która ma ponad 130 000 wierszy i regularnie się zawiesza. Ponieważ pole wartości jest dużym typem tekstu, nawet wyszukiwanie tylko wierszy „autoload” staje się koszmarem wydajności. Te pola wartości są przechowywane oddzielnie od reszty danych wiersza. Mimo że logicznie jest częścią tej samej tabeli, połączenia muszą się odbywać, aby podciągnąć żądane wiersze. Połączenia, które teraz trwają wiecznie, ponieważ potrzebne dane są rozrzucone po całym miejscu na dysku. Udowodniło to profilowanie (przy użyciu profilowania strumieniowego dla mysql).

Dodanie automatycznego ładowania do klucza klastrowego może pomóc rozwiązać ten problem. Klastrowanie przy Autoload Desc, na przykład ID ASC, pozwoliłoby, aby wszystkie wiersze autoloadu zgrupowały się najpierw na dysku. Mimo to myślę, że patrzysz na ogromny wysiłek z perspektywy DB.

Osobiście uważam, że konstrukcja tego systemu jest kiepska. Wygląda na to, że tabela opcji zmieniła się w ogólny haczyk dla wielu rzeczy. To dobrze, jeśli pole wartości jest wystarczająco małe, aby można je było umieścić na tej samej stronie co reszta danych wiersza, i można je skutecznie indeksować. Niestety tak nie jest. Ktokolwiek to zaprojektował, musi wrócić do klasy DB101.

myke
źródło
5
prawda, ale uważają, że gdy rozpoczęła rozwój WordPress, nikt nie myślał, że to osiągnąć mieć tysiące wtyczek Korzystanie z opcji tabeli jako ich przechowywania danych :)
onetrickpony
@onetrickpony, dlatego ważne jest, aby zawsze nie spieszyć się i robić rzeczy dobrze, bez względu na to, czy pewnego dnia będzie to ogromne, czy nie :)
Mahmoud Al-Qudsi