Muszę uruchomić VACUUM FULL bez dostępnego miejsca na dysku

27

Mam jeden stół, który zajmuje prawie 90% miejsca na dysku HD na naszym serwerze. Postanowiłem upuścić kilka kolumn, aby zwolnić miejsce. Ale muszę przywrócić przestrzeń do systemu operacyjnego. Problem jednak polega na tym, że nie jestem pewien, co się stanie, jeśli uruchomię VACUUM FULL i nie będzie wystarczającej ilości wolnego miejsca, aby wykonać kopię tabeli.

Rozumiem, że VACUUM FULL nie powinien być używany, ale pomyślałem, że to najlepsza opcja w tym scenariuszu.

Wszelkie pomysły będą mile widziane.

Używam PostgreSQL 9.0.6

Justin
źródło

Odpowiedzi:

19

Ponieważ nie masz wystarczająco dużo miejsca, aby uruchomić vacumm lub przebudować, zawsze możesz odbudować swoje bazy danych postgresql, przywracając je. Przywracanie baz danych, tabel, indeksów zwalnia miejsce i defragmentację. Następnie możesz skonfigurować automatyczną konserwację, aby regularnie opróżniać bazy danych.

1 Utwórz kopię zapasową wszystkich baz danych na serwerze postgresql

Będziesz chciał wykonać kopię zapasową wszystkich baz danych na partycji, która ma wystarczającą ilość miejsca. Jeśli korzystasz z systemu Linux, możesz użyć gzip, aby dodatkowo skompresować kopię zapasową, aby zaoszczędzić miejsce

su - postgres
pg_dumpall | gzip -9 > /some/partition/all.dbs.out.gz

2 Utwórz kopię zapasową plików konfiguracyjnych

cp /path/to/postgresql/data_directory/*.conf /some/partition/

3 Stop Postgresql

pg_ctl -D /path/to/postgresql/data_directory stop

4 skasuj zawartość katalogu danych

rm -Rf /path/to/postgresql/data_directory/*

5 Uruchom initdb, aby ponownie zainicjować katalog danych

initdb -D /path/to/postgresql/data_directory

6 Przywróć pliki konfiguracyjne

cp /some/partition/*.conf /path/to/postgresql/data_directory/*.conf 

7 Uruchom Postgresql

pg_ctl -D /path/to/postgresql/data_directory start

8 Przywróć zrzut wszystkich utworzonych baz danych

gunzip /some/partition/all.dbs.out.gz
psql -f /some/partition/all.dbs.out
Craig Efrein
źródło
1
Dzięki, to właśnie skończyłem z kilkoma różnicami. Właśnie zrzuciłem bazę danych po utworzeniu kopii zapasowej. Następnie utworzył nowy i przywrócił go.
Justin
Nie ma za co. Uznałem, że usunięcie zawartości katalogu danych i wykonanie initdb byłoby jednak wystarczające.
Craig Efrein
Działa świetnie, po prostu polecam pominięcie gzipczęści, aby zaoszczędzić czas.
Rafael Barbosa
17

UWAGA: Testowałem to na wersji 9.1. Nie mam tutaj żadnego serwera 9.0. Jestem pewien, że preeeettty będzie działało na 9.0.


UWAGA (jak zauważono w komentarzach @erny):

Note that high CPU load due to I/O operations may be expected.

Możesz to zrobić praktycznie bez przestojów, korzystając z tymczasowego obszaru tabel. Czas przestoju będzie miał postać wyłącznych zamków. Ale tylko na stole odkurzasz. Wszystko, co się stanie, to zapytania klientów będą po prostu czekać na uzyskanie blokady, jeśli uzyskają dostęp do danej tabeli. Nie musisz zamykać istniejących połączeń.

Należy jednak pamiętać, że przesuwanie stołu i próżnia pełna będą musiały najpierw poczekać na wyłączność blokady!


Po pierwsze, oczywiście potrzebujesz dodatkowej pamięci. Jak Stéphanewspomniano w komentarzach, musi on być co najmniej dwa razy większy niż tabela, o której mowa, tak jak VACUUM FULLpełna kopia. Jeśli masz szczęście i możesz dynamicznie dodać dysk do komputera, zrób to. W najgorszym przypadku możesz po prostu podłączyć dysk USB (ryzykowny i wolny)!

Następnie zamontuj nowe urządzenie i udostępnij je jako przestrzeń tabel:

CREATE TABLESPACE tempspace LOCATION '/path/to/new/folder';

Możesz łatwo wymienić obszary tabel, używając:

\db

Sprawdź dwukrotnie bieżący obszar tabel (musisz wiedzieć, gdzie go przenieść z powrotem):

SELECT tablespace FROM pg_tables WHERE tablename = 'mytable';

Jeśli tak NULL, będzie w domyślnym obszarze tabel:

SHOW default_tablespace;

Jeśli to jest NULLtak dobrze, to będzie prawdopodobnie pg_default(sprawdź oficjalne dokumenty w przypadku to zmienić).

Teraz przesuń stół:

ALTER TABLE mytable SET TABLESPACE tempspace;
COMMIT;  -- if autocommit is off

Odkurz to:

VACUUM FULL mytable;

Cofnij to:

-- assuming you are using the defaults, the tablespace will be "pg_default".
-- Otherwise use the value from the SELECT we did earlier.
ALTER TABLE mytable SET TABLESPACE pg_default;
COMMIT;  -- if autocommit is off

Usuń tymczasowe miejsce:

DROP TABLESPACE tempspace;
ekshuma
źródło
Uwaga: przeniesienie wydaje się wykorzystywać więcej miejsca na dysku w oryginalnym katalogu danych ...
Chris Withers
Właśnie przetestowałem to na 9.3 i działa jak urok.
Bartek Jabłoński
Z powodzeniem stosowany w produkcji w wersji 9.1. Po zmianie obszaru tabel zwolnione zostaje oryginalne zajęte miejsce. Należy pamiętać, że można oczekiwać dużego obciążenia procesora z powodu operacji we / wy.
erny
2
Niesamowite wskazówki, dziękuję za to szczegółowe wyjaśnienie. Zwróć uwagę, że w tymczasowym obszarze tabel będziesz potrzebował co najmniej size of table x 2, ponieważ VACUUM FULLtworzy pełną kopię tabeli.
Stéphane
Dzięki @ Stéphane. Dodałem te informacje do głównego ciała.
ekshuma
2

Szybko i brudno:

  • Zatrzymaj Postgres
  • Przenieś główny katalog bazy danych na inny dysk, na którym jest wystarczająco dużo miejsca do odkurzania
  • W oryginalnej lokalizacji głównej dodaj dowiązanie symboliczne do nowej lokalizacji
  • Odkurzać
  • Usuń dowiązanie symboliczne i przenieś główny katalog z powrotem do pierwotnej lokalizacji
  • Uruchom Postgres

Na przykład,:

$ service postgresql stop $ mv /var/lib/postgresql/9.5/main /mnt/bigdisk $ ln -sr /mnt/bigdisk/main /var/lib/postgresql/9.5 $ vacuumdb --all --full $ rm /var/lib/postgresql/9.5/main $ mv /mnt/bigdisk/main /var/lib/postgresql/9.5 $ service postgresql start

Roger Dahl
źródło
0

Jeśli masz miejsce na dysku, aby zrobić zrzut i przywrócić, powinieneś mieć miejsce na dysku, aby wykonać próżnię - full. Problem polega na tym, że Vacuumdb --full utworzy kopię całego pliku danych. Co możesz zrobić:

  1. skopiuj pliki, które przechowują ogromną tabelę na inny dysk, na przykład wolniejszy, większy dysk.
  2. twórz symboliczne linki z oryginalnej lokalizacji do nowego miejsca na drugim dysku.
  3. uruchom Vacuumdb --full, teraz powinien odczytać dane z drugiego dysku i zapisać końcową tabelę na oryginalnym dysku danych.
Gunther
źródło