WordPress: usuwanie wygasłych transientów przez WP-CLI

Management Summary
WordPress przechowuje dane tymczasowe, aby nie wykonywać części pracy od nowa przy każdym otwarciu strony. Takie wartości, nazywane transientami, mogą pozostać w bazie po wygaśnięciu ważności. Celowe czyszczenie usuwa wygasłe wpisy, zachowując artykuły, wcześniejsze wersje i powiązania językowe. Artykuł wyjaśnia tę pracę utrzymaniową za pomocą narzędzia poleceń WordPressa. Pozwala to ograniczyć zbędne dane, ale mniejsza baza nie oznacza automatycznie szybszej witryny.
Spis treści
Duża baza WordPressa nie oznacza automatycznie zaniedbanej bazy. Rewizje zachowują wersje tekstu możliwe do odtworzenia, a transienty przechowują dane podręczne. Konserwacja zaczyna się od ustalenia, które dane nie są już potrzebne, ile miejsca rzeczywiście zajmują i które zapytanie działa wolno.
Instrukcja automatyzuje wyłącznie usuwanie wygasłych transientów z bazy. Rewizje, metadane wpisów i powiązania językowe pozostają zachowane. Wymagane są Linux z Bash i flock, sprawdzona instalacja WP-CLI oraz pojedyncza witryna WordPress bez zewnętrznej pamięci obiektowej. Multisite i konfiguracje Redis/Memcached wymagają osobnej procedury.

1. Rozmiar i zawartość to różne kwestie
wp db size --tables --all-tables-with-prefix --human-readable --orderby=size --order=desc wyświetla tabele z właściwym prefiksem malejąco według rozmiaru. Dopiero jawne opcje sortowania ustalają taką kolejność. Wynik nie dowodzi fragmentacji ani określonego spadku wydajności.
WordPress nie musi tworzyć nowej rewizji przy każdym zapisie niezmienionej treści. Zwykłe trwałe usunięcie wpisu przez API WordPressa usuwa również powiązane metadane i relacje. Osierocone rekordy to wpisy, których powiązany obiekt już nie istnieje. Mogą powstać po bezpośrednich zmianach SQL lub błędach rozszerzeń; przed czyszczeniem potrzebne jest zbadanie przyczyny.
Wygasłe transienty są obsługiwane podczas odczytu, a WordPress ma także zaplanowane czyszczenie. Nagromadzenie może więc wskazywać na niewykonywane zdarzenia cron. Przy zewnętrznej pamięci obiektowej transienty nie muszą znajdować się w bazie. Liczenie rekordów czasu ważności w bazie nie opisuje wtedy całego cache.
2. Skrypt o ograniczonym zakresie
Skrypt otrzymuje katalog WordPressa w WP_PATH, istniejący prywatny katalog roboczy w STATE_DIR oraz opcjonalnie bezwzględną ścieżkę WP_BIN. Katalog roboczy musi znajdować się poza wszystkimi publicznie udostępnianymi katalogami i być dostępny tylko dla konta konserwacji. Kontrola ścieżki w skrypcie wykrywa podkatalog WordPressa, ale nie zastępuje sprawdzenia dodatkowych aliasów serwera WWW.
Domyślny tryb audit pokazuje rozmiary tabel, liczbę rewizji i transientów. Liczba transientów obejmuje także nadal ważne wpisy i nie jest podglądem usuwania. Tryb apply najpierw eksportuje bazę, a następnie usuwa wyłącznie wygasłe zwykłe transienty i site transients. W tym przypadku site transients oznaczają specjalnie nazwane wartości pojedynczej instalacji.
#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
export PATH=/usr/local/bin:/usr/bin:/bin
: "${WP_PATH:?Set the WordPress directory}"
: "${STATE_DIR:?Set a private existing directory outside every webroot}"
WP_BIN="${WP_BIN:-/usr/local/bin/wp}"
MODE="${1:-audit}"
[[ "$MODE" == audit || "$MODE" == apply ]] || { echo "Use audit or apply" >&2; exit 2; }
[[ -x "$WP_BIN" && -d "$WP_PATH" && -d "$STATE_DIR" ]] || { echo "Invalid paths" >&2; exit 2; }
WP_PATH=$(realpath "$WP_PATH")
STATE_DIR=$(realpath "$STATE_DIR")
case "$STATE_DIR/" in "$WP_PATH/"*) echo "State directory is inside WordPress" >&2; exit 2;; esac
exec 9>"$STATE_DIR/maintenance.lock"
flock -n 9 || { echo "Another maintenance run holds the lock" >&2; exit 75; }
trap 'status=$?; echo "FAILED (exit $status); inspect the last completed step" >&2; exit "$status"' ERR
wp_run() { "$WP_BIN" --path="$WP_PATH" "$@"; }
wp_run core is-installed
wp_run eval 'if (is_multisite() || wp_using_ext_object_cache()) { WP_CLI::error("Example requires single-site without external object cache"); }'
wp_run db size --tables --all-tables-with-prefix --human-readable --orderby=size --order=desc
printf '%s\n' "Revision count (not scheduled for deletion):"
wp_run post list --post_type=revision --post_status=inherit --format=count
printf '%s\n' "Database transient count (includes unexpired entries):"
wp_run transient list --format=count
if [[ "$MODE" == audit ]]; then
printf '%s\n' "Audit finished; no cleanup commands executed."
exit 0
fi
wp_run eval 'global $wpdb; $rows=$wpdb->get_results("SHOW TABLE STATUS"); if ($wpdb->last_error || !$rows) { WP_CLI::error("Table engine check failed"); } foreach ($rows as $row) { if ($row->Engine !== null && $row->Engine !== "InnoDB") { WP_CLI::error("Backup example requires InnoDB tables"); } }'
partial=$(mktemp "$STATE_DIR/backup-$(date -u +%Y%m%dT%H%M%SZ)-XXXXXX.sql.partial")
wp_run db export "$partial" --single-transaction --skip-lock-tables
[[ -s "$partial" ]] || { echo "Empty backup; cleanup blocked" >&2; exit 1; }
backup="${partial%.partial}"
mv -- "$partial" "$backup"
printf 'Backup created: %s\n' "$backup"
wp_run transient delete --expired
wp_run transient delete --expired --network
printf '%s\n' "Expired-transient cleanup completed."
Blokada zapobiega równoległym przebiegom tego skryptu z tym samym katalogiem roboczym. Nie blokuje innych narzędzi konserwacji ani ruchu witryny. Błąd kończy wykonanie bez automatycznego cofania zakończonych kroków. Jeśli druga operacja usuwania zakończy się błędem, pierwsza mogła już zostać wykonana.
Eksport korzysta ze spójnej transakcji dla tabel InnoDB. W tym czasie nie wolno zmieniać struktury tych tabel, na przykład dodawać lub usuwać kolumn. Kontrola silnika sprawdza sposób przechowywania danych tabel i odrzuca rozwiązania inne niż InnoDB. Udany eksport i niepusty plik nie zastępują testu odtworzenia. Zrzut może zawierać dane osobowe i sekrety; dostęp, retencja, wolne miejsce i niezależna kopia wymagają ustalenia przed pracą cykliczną. Nieudane pliki częściowe pozostają do analizy.
3. Najpierw test na oddzielnej kopii
Skrypt powinien znajdować się w pliku zarządzanym administracyjnie, który konto wykonujące może odczytać i uruchomić, ale nie zmienić. Prywatny katalog roboczy wymaga prawa zapisu dla tego konta. WP-CLI potrzebuje dostępu do konfiguracji WordPressa i bazy; rutynowe uruchamianie jako root nie jest konieczne.
Pierwszy przebieg używa rzeczywistych ścieżek i trybu audit. Nawet ten tryb ładuje WordPress i rozszerzenia, więc inicjalizacja wtyczek nie musi być całkowicie pozbawiona zapisów. Przed apply eksport i odtworzenie wymagają próby na oddzielnej instancji. Testy błędów obejmują nieprawidłową ścieżkę, nieudany eksport i drugie równoległe uruchomienie.
Kontrola nie kończy się na rozmiarze pliku. Wymagane jest sprawdzenie strony głównej, edycji, przełączania języka, kategorii i wybranych funkcji. Usunięcie transientów może uruchomić ponowne obliczenia cache i chwilowo zwiększyć obciążenie. WP-CLI nadal korzysta z PHP i bazy; brak jakiegokolwiek obciążenia nie jest prawidłową obietnicą.
4. Cron z widocznym wynikiem
Po udanych testach crontab konta konserwacji może zawierać stałe wartości WP_PATH, STATE_DIR i WP_BIN. Przykładowy harmonogram to 0 3 * * 0 /bin/bash /opt/scripts/wp-transients.sh apply. Ten zapis planuje uruchomienie w niedziele o 03:00 w strefie czasowej usługi cron. Ścieżka i godzina wymagają dostosowania; /opt/scripts/wp-transients.sh oznacza wybrane miejsce instalacji pokazanego skryptu.
Wynik nie powinien znikać w /dev/null. Poczta crona wymaga działającego transportu wiadomości. Alternatywa potrzebuje dziennika dostępnego tylko dla uprawnionych kont, z ograniczeniem rozmiaru plików i czasu przechowywania oraz sprawdzonego powiadamiania o błędach. Brak oczekiwanego udanego przebiegu również powinien być wykrywany. Wyłączony komputer lub zatrzymany demon cron nie wykonuje zadania.
Strefa czasowa i obsługa zmiany czasu zależą od zainstalowanej implementacji crona. Stały wpis nie gwarantuje startu dokładnie co do sekundy ani poprawnego zakończenia. Ścieżka WP-CLI i ograniczone środowisko crona wymagają testu na rzeczywistym koncie.
5. Osobne decyzje o rewizjach i przebudowie tabel
Limit rewizji, na przykład define( 'WP_POST_REVISIONS', 3 );, zachowuje ograniczoną historię. Istniejąca definicja wymaga zmiany zamiast powielenia. Limit jest stosowany podczas tworzenia nowych rewizji; samo ustawienie stałej nie czyści natychmiast całego archiwum. Autosave i filtry rozszerzeń wymagają dodatkowego uwzględnienia.
wp db optimize nie jest koniecznym dodatkiem wykonywanym co tydzień. Dla MySQL InnoDB OPTIMIZE może przebudować tabelę; nawet online DDL, czyli zmiana struktury podczas działania bazy, wymaga blokad w określonych fazach. Zachowanie zależy od miejsca, cech tabeli, silnika i wersji. MariaDB ma własne warianty. Zmniejszenie pliku lub określone przyspieszenie nie są gwarantowane. Podstawą są zmierzone problemy i zaplanowane okno konserwacji.
Pytania i odpowiedzi
Dlaczego brak zbiorczego usuwania relacji taksonomii?
term_relationships.object_id nie zawsze oznacza wpis. Polylang wykorzystuje tabelę między innymi do języków i tłumaczeń kategorii oraz tagów. Połączenie wyłącznie z tabelą wpisów może usunąć prawidłowe relacje, a przypadkowo zgodne identyfikatory ukryć część szkód. Takie naprawy wymagają konkretnego, merytorycznie sprawdzonego wyboru rekordów.
Czy baza zmniejszy się o 40–60 procent?
Brak podstaw do ogólnego procentu. Usunięte wiersze, miejsce do ponownego użycia wewnątrz tabeli i przestrzeń zwrócona systemowi operacyjnemu są różnymi wielkościami. Czas konkretnych zapytań również wymaga osobnego pomiaru.
Czy wystarczy kopia w tym samym katalogu?
Lokalny eksport pomaga przed zmianą, ale nie chroni przed awarią tego nośnika. Nadal potrzebne są niezależna kopia i sprawdzona procedura odtworzenia. Odtwarzanie nad bazą używaną od czasu kopii może nadpisać nowsze zmiany i wymaga zaplanowania.