Perché ho ricevuto l'errore "No space left on device" o "DiskFull" su Amazon RDS per PostgreSQL?

10 minuti di lettura
0

Dispongo di un piccolo database Amazon Relational Database Service (Amazon RDS) per PostgreSQL. Lo spazio di archiviazione disponibile per l'istanza sta diminuendo e ricevo il seguente errore: "Messaggio di errore: PG::DiskFull: ERROR: could not extend file "base/16394/5139755": No space left on device. HINT: Check free disk space." Vorrei risolvere gli errori DiskFull e prevenire eventuali problemi di archiviazione.

Descrizione breve

Nell'archivio delle istanze del database di Amazon RDS vengono conservati:

  • file temporanei o tabelle creati per mezzo di transazioni PostgreSQL;
  • file di dati;
  • log WAL (Write-Ahead Log);
  • slot di replica;
  • file di log del database (file di errore) conservati da troppo tempo;
  • altri file DB o Linux utilizzati per mantenere costante lo stato delle istanze.

Risoluzione

1.     Amazon CloudWatch consente di monitorare lo spazio di archiviazione del database per mezzo della metrica FreeStorageSpace. Permette inoltre di impostare un allarme che invierà una notifica non appena lo spazio disponibile sarà quasi esaurito. In caso di avviso, si consiglia di fare riferimento alle cause comuni relative ai problemi di archiviazione menzionate in precedenza.

2.    Se l'istanza del database occupa ancora più spazio di archiviazione del previsto, è necessario verificare:

  • le dimensioni dei file di log del database;
  • la presenza di eventuali file temporanei;
  • un utilizzo del disco in costante aumento da parte dei log delle transazioni;
  • gli slot di replica:
  • fisici, creati da repliche di lettura tra regioni o nella stessa regione laddove siano eseguiti su PostgreSQL 14.1 o su una versione successiva;
  • logici, creati per una replica o abbonato;
  • la presenza di un "bloat" o di stringhe inutilizzate mai rimosse;
  • la presenza di file orfani.

3.    Davanti a un carico di lavoro prevedibile è possibile abilitare l'estensibilità automatica dello spazio di archiviazione per l'istanza. In questo modo, non appena Amazon RDS rileverà che lo spazio libero nel database è quasi esaurito, ridimensionerà automaticamente l'archivio. Amazon RDS avvierà questa modifica se:

  • lo spazio libero disponibile è inferiore al 10% rispetto a quello assegnato;
  • la condizione carente persiste per almeno 5 minuti;
  • sono trascorse almeno 6 ore dall'ultima ottimizzazione o modifica dell'archivio completata nell'ambito dell'istanza.

L'estensibilità automatica dell'istanza del database, inoltre, può essere limitata impostando una soglia massima di archiviazione. Per ulteriori informazioni, consulta la pagina dedicata.

Verificare la dimensione dei file di log del database

Per impostazione predefinita, i file di log degli errori di Amazon RDS per PostgreSQL vengono conservati per 4.320 minuti (3 giorni). Quelli di grandi dimensioni possono occupare più spazio per via di carichi di lavoro più elevati o registrazioni eccessive. Questo periodo di conservazione può essere modificato per mezzo del parametro rds.log_retention_period, disponibile nel gruppo di parametri associato all'istanza del database. Portando il valore a 1.440, ad esempio, i log verranno conservati per 1 giorno. Ulteriori informazioni sono disponibili nella pagina dedicata ai file di log del database PostgreSQL.

Inoltre, nel gruppo di parametri del database è possibile modificare quelli relativi alla segnalazione e alla registrazione degli errori, in modo da scongiurare una rilevazione eccessiva. Questo ridurrà a sua volta le dimensioni del file di log. Ulteriori informazioni sono disponibili nella pagina dedicata alla segnalazione e alla registrazione degli errori.

Verificare la presenza di file temporanei

I file temporanei sono documenti che vengono archiviati a ogni connessione del backend o sessione. Questi vengono impiegati come pool di risorse. Per esaminare le statistiche dei file temporanei è possibile eseguire un comando simile a questo:

psql=> SELECT datname, temp_files AS "Temporary files",temp_bytes AS "Size of temporary files" FROM pg_stat_database ;

Importante: le colonne temp_files e temp_bytes nella vista pg_stat_database raccolgono statistiche in forma aggregata (cumulativa). Ciò è dovuto al fatto che questi contatori vengono azzerati soltanto dopo il ripristino all'avvio del server. Vengono dunque resettati dopo un arresto forzato, un crash del server o un ripristino point-in-time (PITR). Per questo motivo, oltre all'output, è consigliabile monitorare anche il numero e le dimensioni di questi file.

I file temporanei vengono creati per ogni richiesta di ordinamento o hashing, e per i risultati relativi a una query temporanea. Per tenere traccia delle tabelle e dei file temporanei creati, è possibile configurare il parametro log_temp_files in un gruppo di parametri personalizzato. Questo aiuta a monitorare i log relativi ai nomi e alle dimensioni dei file temporanei. Impostando il valore log_temp_files su 0, tutte le informazioni sul file temporaneo verranno registrate. Utilizzando un valore positivo, il sistema registrerà soltanto i dati dei file di dimensioni uguali o superiori al numero di KB specificato. L'impostazione predefinita è -1, che disabilita completamente la registrazione.

Con l'opzione **EXPLAIN ANALYZE ** all'interno della query è inoltre possibile verificare l'ordinamento del disco. Un esame dell'output del log permette di analizzare la dimensione dei file temporanei creati dalla query. Ulteriori informazioni sono disponibili nella documentazione di PostgreSQL dedicata alla verifica dell'attività del database.

Verificare la presenza di un aumento sospetto nell'utilizzo del disco da parte dei log delle transazioni

La metrica CloudWatch per TransactionLogsDiskUsage rappresenta lo spazio su disco utilizzato dai WAL delle transazioni. L'utilizzo del disco da parte del log delle transazioni può aumentare a causa di:

  • carichi elevati a livello di database (scritture e aggiornamenti che generano WAL aggiuntivi);
  • ritardo nel flusso dei dati relativi alla replica di lettura nella stessa regione o replica di lettura effettuata ad archivio pieno;
  • slot di replica;

Gli slot di replica possono essere creati come parte della funzionalità di decodifica logica di AWS Database Migration Service (AWS DMS). Per la replica logica, il parametro rds.logical_replication dello slot è impostato su 1. Gli slot di replica conservano i file WAL fino all'utilizzo di questi ultimi da parte di un consumatore come pg_recvlogical, estrazione, trasformazione e caricamento (ETL) o AWS DMS.

Con rds.logical_replication regolato su 1, AWS RDS imposterà i parametri wal_level, max_wal_senders, max_replication_slots e max_connections. La modifica di questi parametri può aumentare il numero di WAL creati. È consigliabile impostare il parametro rds.logical_replication solo quando si utilizzano slot logici. Indicare il valore 1 per il parametro in assenza di un consumatore per i file WAL conservati dallo slot di replica, anche se in presenza di slot di replica logici, può generare un aumento in termini di utilizzo del disco da parte dei log delle transazioni. Ciò comporterebbe anche una riduzione costante dello spazio di archiviazione disponibile.

Questa query consente di confermare la presenza e le dimensioni degli slot di replica:

PostgreSQL v9:

psql=> SELECT slot_name, pg_size_pretty(pg_xlog_location_diff(pg_current_xlog_location(),restart_lsn)) AS
replicationSlotLag, active FROM pg_replication_slots ;

PostgreSQL v10 e versioni successive:

psql=> SELECT slot_name, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),restart_lsn)) AS replicationSlotLag,
active FROM pg_replication_slots ;

Una volta identificato lo slot di replica non in uso (con stato attivo impostato su False), è possibile eliminarlo eseguendo questa query:

psql=> SELECT pg_drop_replication_slot('Your_slotname_name');

Nota: se un'attività di AWS DMS è il consumatore e non è più necessaria, è necessario eliminare sia quest'ultima che, manualmente, lo slot di replica.

Esempio di output:

slot_name                                                      | replicationslotlag | active
---------------------------------------------------------------+--------------------+--------
xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d    | 129 GB             | f
7pajuy7htthd7sqn_00013322_a27bcebf_7d0f_4124_b336_92d0fb9f5130 | 704 MB             | t
zp2tkfo4ejw3dtlw_00013322_03e77862_689d_41c5_99ba_021c8a3f851a | 624 MB             | t

In questo esempio, lo slot ** xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d** ha lo stato attivo impostato su False. Ciò significa che non viene utilizzato attivamente. Lo slot occupa ugualmente 129 GB come file di transazione.

Questo comando permette di eliminare la query:

psql=> SELECT pg_drop_replication_slot('xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d');

Verificare lo stato delle repliche di lettura tra regioni

All'utilizzo di una replica di lettura tra regioni si crea uno slot di replica fisico sull'istanza principale. E se la replica di lettura fallisce, lo spazio di archiviazione sull'istanza primaria del database può risentirne. Ciò è dovuto al fatto che i file WAL non vengono copiati nella replica di lettura. Per determinare il ritardo della replica con il lag maggiore è possibile utilizzare le metriche di CloudWatch, il parametro Oldest Replication Slot Lag e l'opzione Transaction Logs Disk Usage. Inoltre, è possibile quantificare lo spazio di archiviazione utilizzato per i dati WAL.

Per verificare lo stato della replica di lettura tra regioni, si consiglia di utilizzare query pg_replication_slots.. Ulteriori informazioni sono disponibili nella documentazione di PostgreSQL dedicata a pg_replication_slots. Se lo stato attivo viene restituito come Falso, significa che attualmente lo slot non è utilizzato per la replica.

psql=> SELECT * FROM pg_replication_slots;

Per verificare le statistiche relative alla replica è possibile usare la vista pg_stat_replication sull'istanza di origine. Ulteriori informazioni sono disponibili nella documentazione di PostgreSQL relativa a pg_stat_replication.

Verificare la presenza di un "bloat" o di stringhe inutilizzate mai rimosse (tuple)

Nelle normali operazioni di PostgreSQL, le tuple eliminate o rese obsolete da un AGGIORNAMENTO non vengono rimosse dalla relativa tabella. Per le implementazioni di Multi-Version Concurrency Control (MVCC), quando viene eseguita un'operazione DELETE la riga non viene immediatamente rimossa dal file di dati. Piuttosto, viene contrassegnata come eliminata attivando il campo xmax in una delle intestazioni. Nel corso di un aggiornamento, prima vengono contrassegnate le righe da eliminare, quindi viene eseguita un'operazione di inserimento. Ciò consente la concorrenza con un numero minimo di inserimenti tra le diverse transazioni. Di conseguenza, come parte del processo MVCC vengono conservate diverse versioni della stessa riga.

Se le righe inutilizzate non vengono eliminate, restano nei file di dati, seppure invisibili ai fini delle transazioni, con un impatto sullo spazio disponibile su disco. Se una tabella contiene molte operazioni di tipo DELETE e UPDATE, le tuple inutilizzate potrebbero occupare una grande quantità di spazio su disco, spazio che a volte viene chiamato "bloat" in PostgreSQL.

L'operazione VACUUM consente di liberare lo spazio su disco occupato dalle tuple inattive, ma non di destinarlo nuovamente all'archivio. Per fare questo sarà necessario eseguire l'operazione VACUUM FULL. Nota, tuttavia, che durante l'esecuzione la tabella verrà temporaneamente bloccata. Questo metodo richiede anche dello spazio aggiuntivo su disco, poiché prevede la scrittura di una nuova copia della tabella ed eliminerà la vecchia versione solo quando l'operazione sarà completa. È quindi consigliabile utilizzarlo solo quando lo spazio da recuperare all'interno della tabella risulti significativo. Si raccomanda inoltre di eseguire operazioni periodiche di VACUUM e AUTOVACUUM sulle tabelle che vengono aggiornate di frequente. Ulteriori informazioni sono disponibili nella documentazione di PostgreSQL dedicata all'operazione VACUUM.

È possibile verificare il numero stimato di tuple inutilizzate tramite la vista pg_stat_all_tables. Ulteriori informazioni sono disponibili nella documentazione di PostgreSQL relativa alla vista pg_stat_all_tables. In questo esempio, sono state rilevate 1.999.952 tuple inutilizzate (n_dead_tup):

psql => SELECT * FROM pg_stat_all_tables WHERE relname='test';

-[ RECORD 1 ]-------+------------------------------
relid               | 16395
schemaname          | public
relname             | test
seq_scan            | 3
seq_tup_read        | 5280041
idx_scan            |
idx_tup_fetch       |
n_tup_ins           | 2000000
n_tup_upd           | 0
n_tup_del           | 3639911
n_tup_hot_upd       | 0
n_live_tup          | 1635941
n_dead_tup          | 1999952
n_mod_since_analyze | 3999952
last_vacuum         |
last_autovacuum     | 2018-08-16 04:49:52.399546+00
last_analyze        | 2018-08-09 09:44:56.208889+00
last_autoanalyze    | 2018-08-16 04:50:22.581935+00
vacuum_count        | 0
autovacuum_count    | 1
analyze_count       | 1
autoanalyze_count   | 1


psql => VACUUM TEST;

Verificare la presenza di file orfani

I file orfani sono quelli presenti nella directory del database, ma privi di collegamenti diretti. Ciò può accadere nei casi in cui l'istanza esaurisce lo spazio di archiviazione o laddove si verifichi un crash nel corso di un'operazione come ALTER TABLE, VACUUM FULL o CLUSTER. I seguenti passaggi consentono di verificare la presenza di file orfani:

1.    Accedere a PostgreSQL in ogni database

2.    Eseguire queste query per valutare lo spazio utilizzato e le dimensioni reali

# Size of the database occupied by files
psql=> SELECT pg_size_pretty(pg_database_size('DATABASE_NAME'));

# Size of database retrieved by summing the objects (real size)
psql=> SELECT pg_size_pretty(SUM(pg_relation_size(oid))) FROM pg_class;

3.    Prendere nota dei risultati Se la differenza è significativa, è possibile che i file orfani stiano utilizzando spazio di archiviazione.


Informazioni correlate

Utilizzo delle repliche di lettura per Amazon RDS per PostgreSQL

Strumenti di monitoraggio automatici