Polecenia usuwania w WP-CLI: których tabel dotyka każde z nich i co pozostawia

Spis treści
Pielęgnacja bazy w WordPressie to garść poleceń, które wyglądają jednakowo i zachowują się zupełnie inaczej. Jedno idzie przez aplikację i sprząta po sobie; kolejne dotyka jednej tabeli i zostawia cztery inne z wierszami, które nie wskazują już na nic.
Różnica staje się istotna dlatego, że WP-CLI poza nielicznymi wyjątkami nie zna przebiegu próbnego. Zapytanie polecenia kasującego, co by zrobiło, nie jest przewidziane. Jest tylko nawyk zapytania wcześniej innego polecenia.

Wzorzec dwóch kroków zastępujący przebieg próbny
Do każdego polecenia niszczącego istnieje nieszkodliwe rodzeństwo przyjmujące ten sam filtr. Do wp post delete należy wp post list, do wp comment delete należy wp comment list. Uruchomienie listy najpierw z --format=count odpowiada na jedyne pytanie, na które odpowiedziałby przebieg próbny: o ile wierszy zaraz chodzi.
# 0. kopia zapasowa, poza katalogiem serwowanym przez WWW
wp db export /home/pi/kopia-$(date +%F).sql
# 1. policzyć, dokładnie tym filtrem, który zaraz zostanie użyty
wp post list --post_type=revision --format=count
# 2. usunąć, dokładnie tym samym filtrem
wp post list --post_type=revision --format=ids | xargs -n 100 wp post delete --force
xargs w ostatnim wierszu nie jest ozdobą. Wstawienie kilku tysięcy numerów wprost do wiersza poleceń wpada w ograniczenie długości argumentów, a błąd przychodzi, gdy część pracy jest już zrobiona, zamiast zanim cokolwiek się wydarzy – czyli dokładnie w sytuacji, której całe postępowanie miało uniknąć.
Wiersz z kopią zawiera szczegół warty zapamiętania: bez ścieżki wp db export zapisuje zrzut do bieżącego katalogu, a przy poleceniu WordPressa jest nim zwykle katalog serwowany przez WWW. Pełny zrzut bazy o odgadywalnej nazwie, wydawany po HTTP, to wynik gorszy niż wszystko, co porządkowanie miało naprawić.
Dwie drogi do usunięcia tego samego wiersza
wp post delete wywołuje tę samą funkcję co edytor. Usuwa metadane, komentarze, meta komentarzy i powiązania terminów oraz uruchamia haki, przez które rozszerzenia mogą usunąć to, co założyły gdzie indziej – wpis w indeksie wyszukiwania, pamięć podręczną, wiersz we własnej tabeli.
Bezpośrednie DELETE FROM wp_posts usuwa jeden wiersz. Wszystko, co na niego wskazywało, zostaje – nieosiągalne i niewidoczne: żadne zapytanie nie łączy się z wpisem, którego nie ma, więc te wiersze po prostu nigdy się już nie pojawiają. Da się z tym żyć, dopóki numer nie zostanie przydzielony ponownie – a numery wpisów przydziela się ponownie po imporcie bazy. Wtedy nowy wpis bezgłośnie dziedziczy pola własne i komentarze starego.
Czego naprawdę dotyka każde polecenie
| Polecenie | Usuwa | Zostawia |
|---|---|---|
wp post delete <nr> --force |
wpis, metadane, komentarze, terminy | załączone pliki i ich wiersze załączników |
wp post delete <załącznik> --force |
wiersz i pliki na dysku, wszystkie rozmiary | odwołania do adresu w innych wpisach |
wp post delete <rewizje> |
rewizje i ich własne wiersze meta | sam wpis, nietknięty |
wp comment delete --status=spam |
komentarze i meta komentarzy | liczniki komentarzy przy wpisach, do przeliczenia |
wp transient delete --expired |
tylko transjenty, którym minął termin | każdy transjent zapisany bez terminu |
wp db optimize |
nic | blokadę tabeli na czas przebudowy |
Pierwszy wiersz zaskakuje najczęściej. Usunięcie wpisu nie usuwa zawartych w nim obrazów – załączniki są osobnymi wpisami z własnymi numerami i przeżywają swojego rodzica. Witryna odchudzona o tysiąc starych wpisów nadal niesie ze sobą tysiąc wpisów mediów, i tam właśnie zostało miejsce na dysku.
Wiersz z licznikami komentarzy najtaniej naprawić i najłatwiej zapomnieć: po każdym większym kasowaniu komentarzy wp comment recount przywraca zgodność liczb z wierszami. Bez tego nic się nie psuje; liczniki są po prostu błędne, wszędzie i bezgłośnie.
Kosz nie jest kopią zapasową
Bez --force kasowanie przenosi wpis do kosza, a to zmiana statusu i nic więcej. Wiersz zostaje, metadane zostają, media zostają, a miejsce się nie zwalnia – kosz opróżniany raz w miesiącu to nawyk porządkowy, a nie siatka bezpieczeństwa.
Z --force wpis pomija kosz całkowicie i wewnątrz WordPressa nie ma żadnego powrotu. Między pomylonym filtrem a straconym miesiącem stoi wyłącznie zrzut z kroku zerowego – i dlatego jest to krok zerowy.
Przeterminowane to nie to samo co wszystkie
Transjenty to pamięć podręczna z terminem zapisanym obok wartości. wp transient delete --expired usuwa te, którym czas minął, i z założenia jest bezpieczne: co usuwa, i tak było już nieważne.
--all to inne polecenie w tym samym przebraniu. Usuwa również transjenty bez terminu, a niektóre rozszerzenia używają właśnie ich jako jedynego miejsca przechowywania czegoś, czego wyliczenie było drogie – sprawdzenia licencji, stanu magazynu, gotowego menu. Widocznie nic się nie psuje; witryna spędza tylko następną godzinę na odbudowywaniu rzeczy, o które nikt jej nie prosił, a jedno czy dwa rozszerzenia zachowują się, jakby dopiero co je zainstalowano.
Optymalizacja to przebudowa, a nie sprzątanie
wp db optimize wykonuje OPTIMIZE TABLE, a przy InnoDB nie jest to optymalizacja, tylko pełna przebudowa tabeli wraz z indeksami. Na ten czas tabela jest zablokowana do zapisu, co przy małym blogu trwa sekundę, a przy dużej wp_postmeta dostatecznie długo, by odwiedzający to zauważyli.
To zarazem krok, który najpewniej niczego nie odzyskuje. Miejsce po usuniętych wierszach InnoDB wykorzystuje ponownie dla nowych; plik na dysku kurczy się tylko wtedy, gdy usunięto bardzo dużo i od tego czasu nic nie zapisano. Raz po dużym porządkowaniu, o spokojnej godzinie – warto; trzymanie tego w nocnym cronie – nie warto, a właśnie tam polecenie zwykle ląduje.