Diskutrymme är en krävande resurs nuförtiden. Du kommer vanligtvis att vilja lagra data så länge som möjligt, men detta kan vara ett problem om du inte vidtar nödvändiga åtgärder för att förhindra ett potentiellt problem med "utom diskutrymme".
I den här bloggen kommer vi att se hur vi kan upptäcka det här problemet för PostgreSQL, förhindra det, och om det är för sent, några alternativ som förmodligen kommer att hjälpa dig att åtgärda det.
Hur man identifierar PostgreSQL-diskutrymmesproblem
Om du tyvärr befinner dig i denna situation utan diskutrymme kommer du att kunna se några fel i PostgreSQL-databasloggarna:
2020-02-20 19:18:18.131 UTC [4400] LOG: could not close temporary statistics file "pg_stat_tmp/global.tmp": No space left on device
eller till och med i din systemlogg:
Feb 20 19:29:26 blog-pg1 rsyslogd: imjournal: fclose() failed for path: '/var/lib/rsyslog/imjournal.state.tmp': No space left on device [v8.24.0-41.el7_7.2 try http://www.rsyslog.com/e/2027 ]
PostgreSQL kan fortsätta att fungera ett tag med att köra skrivskyddade frågor, men så småningom kommer det att misslyckas med att försöka skriva till disken, då kommer du att se något liknande i din klientsession:
WARNING: terminating connection because of crash of another server process
DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
HINT: In a moment you should be able to reconnect to the database and repeat your command.
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
Om du sedan tittar på diskutrymmet kommer du att få denna oönskade utdata...
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/pve-vm--125--disk--0 30G 30G 0 100% /
Hur man förhindrar PostgreSQL-diskutrymmesproblem
Det huvudsakliga sättet att förhindra den här typen av problem är att övervaka diskutrymmesanvändningen och databas- eller diskanvändningens tillväxt. För detta bör en graf vara ett vänligt sätt att övervaka diskutrymmesökningen:
Och samma sak för databasens tillväxt:
En annan viktig sak att övervaka är replikeringsstatusen. Om du har en replik och av någon anledning slutar den att fungera, beroende på konfigurationen, kan det vara möjligt att PostgreSQL lagrar alla WAL-filer för att återställa repliken när den kommer tillbaka.
Allt detta övervakningssystem är inte meningsfullt utan ett varningssystem att veta när du behöver vidta åtgärder:
Hur man åtgärdar PostgreSQL-diskutrymmesproblem
Tja, om du står inför detta problem med ledigt diskutrymme även med övervaknings- och varningssystemet implementerat (eller inte), finns det många alternativ för att försöka lösa problemet utan att förlora data (eller mindre som möjligt).
Vad förbrukar ditt diskutrymme?
Det första steget bör vara att avgöra var mitt diskutrymme finns. En bästa praxis är att ha separata partitioner, minst en separat partition för din databaslagring, så att du enkelt kan bekräfta om din databas eller ditt system använder för mycket diskutrymme. En annan fördel med detta är att minimera skadorna. Om din rotpartition är full kan din databas fortfarande skriva i sin egen partition utan problem.
Användning av databasutrymme
Låt oss se några användbara kommandon för att kontrollera din databasdiskutrymmesanvändning.
Ett grundläggande sätt att kontrollera databasutrymmesanvändning är att kontrollera datakatalogen i filsystemet:
$ du -sh /var/lib/pgsql/11/data/
819M /var/lib/pgsql/11/data/
Eller om du har en separat partition för din datakatalog kan du använda df -h direkt.
PostgreSQL-kommandot "\l+" listar databaserna som lägger till storleksinformation:
$ postgres=# \l+
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace
| Description
-----------+----------+-----------+---------+-------+-----------------------+---------+------------
+--------------------------------------------
postgres | postgres | SQL_ASCII | C | C | | 7965 kB | pg_default
| default administrative connection database
template0 | postgres | SQL_ASCII | C | C | =c/postgres +| 7817 kB | pg_default
| unmodifiable empty database
| | | | | postgres=CTc/postgres | |
|
template1 | postgres | SQL_ASCII | C | C | =c/postgres +| 7817 kB | pg_default
| default template for new databases
| | | | | postgres=CTc/postgres | |
|
world | postgres | SQL_ASCII | C | C | | 8629 kB | pg_default
|
(4 rows)
Genom att använda pg_database_size och databasnamnet kan du se databasens storlek:
postgres=# SELECT pg_database_size('world');
pg_database_size
------------------
8835743
(1 row)
Och att använda pg_size_pretty för att se detta värde på ett läsbart sätt kan vara ännu bättre:
postgres=# SELECT pg_size_pretty(pg_database_size('world'));
pg_size_pretty
----------------
8629 kB
(1 row)
När du vet var utrymmet finns kan du vidta motsvarande åtgärd för att fixa det. Tänk på att det inte räcker att bara ta bort rader för att återställa diskutrymmet, du måste köra en VACUUM eller VACUUM FULL för att slutföra uppgiften.
Loggfiler
Det enklaste sättet att återställa diskutrymme är genom att ta bort loggfiler. Du kan kontrollera PostgreSQL-loggkatalogen eller till och med systemloggarna för att verifiera om du kan få lite utrymme därifrån. Om du har något liknande:
$ du -sh /var/lib/pgsql/11/data/log/
18G /var/lib/pgsql/11/data/log/
Du bör kontrollera kataloginnehållet för att se om det finns ett problem med loggrotation/lagring eller om något händer i din databas och skriver det till loggarna.
$ ls -lah /var/lib/pgsql/11/data/log/
total 18G
drwx------ 2 postgres postgres 4.0K Feb 21 00:00 .
drwx------ 21 postgres postgres 4.0K Feb 21 00:00 ..
-rw------- 1 postgres postgres 18G Feb 21 14:46 postgresql-Fri.log
-rw------- 1 postgres postgres 9.3K Feb 20 22:52 postgresql-Thu.log
-rw------- 1 postgres postgres 3.3K Feb 19 22:36 postgresql-Wed.log
Innan du tar bort loggarna, om du har en stor, är en bra praxis att behålla de sista 100 raderna eller så och sedan ta bort dem. Så du kan kontrollera vad som händer efter att ha genererat ledigt utrymme.
$ tail -100 postgresql-Fri.log > /tmp/log_temp.log
Och sedan:
$ cat /dev/null > /var/lib/pgsql/11/data/log/postgresql-Fri.log
Om du bara tar bort den med "rm" och loggfilen används av PostgreSQL-servern (eller en annan tjänst) kommer inte utrymme att frigöras, så du bör trunkera den här filen med denna cat / kommandot dev/null istället.
Denna åtgärd är endast för PostgreSQL och systemloggfiler. Ta inte bort pg_wal-innehållet eller någon annan PostgreSQL-fil eftersom det kan orsaka allvarlig skada på din databas.
Bloat
I en normal PostgreSQL-operation tas tupler som raderas eller föråldras av en uppdatering inte fysiskt bort från tabellen; de är närvarande tills ett VAKUUM utförs. Så det är nödvändigt att göra VAKUUM regelbundet (AUTOVAKUUM), särskilt i ofta uppdaterade tabeller.
Problemet här är att utrymme inte returneras till operativsystemet med bara VACUUM, det är endast tillgängligt för användning i samma tabell.
VACUUM FULL skriver om tabellen till en ny diskfil, vilket återställer det oanvända utrymmet till operativsystemet. Tyvärr kräver det ett exklusivt lås på varje bord medan det är igång.
Du bör kontrollera tabellerna för att se om en VAKUUM (FULL) process krävs.
replikeringsplatser
Om du använder replikeringsplatser och det av någon anledning inte är aktivt:
postgres=# SELECT slot_name, slot_type, active FROM pg_replication_slots;
slot_name | slot_type | active
-----------+-----------+--------
slot1 | physical | f
(1 row)
Det kan vara ett problem för ditt diskutrymme eftersom det kommer att lagra WAL-filerna tills de har tagits emot av alla standbynoder.
Sättet att fixa det är att återställa repliken (om möjligt), eller ta bort platsen:
postgres=# SELECT pg_drop_replication_slot('slot1');
pg_drop_replication_slot
--------------------------
(1 row)
Så utrymmet som används av WAL-filerna kommer att frigöras.
Slutsats
Som vi nämnde är övervaknings- och varningssystem nycklarna för att undvika den här typen av problem. På så sätt kan ClusterControl hjälpa dig att ha dina system igång, skicka larm till dig när det behövs eller till och med vidta återställningsåtgärder för att hålla ditt databaskluster igång. Du kan också distribuera/importera olika databastekniker och skala ut dem vid behov.