PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come ottenere il meglio dai log di PostgreSQL

In quanto moderno RDBMS, PostgreSQL include molti parametri per la messa a punto. Una delle aree da considerare è come PostgreSQL dovrebbe registrare le sue attività. La registrazione è spesso trascurata nella gestione del database di Postgres e, se non viene ignorata, di solito viene impostata in modo errato. Ciò accade perché la maggior parte delle volte lo scopo della registrazione non è chiaro. Naturalmente, il motivo fondamentale per la registrazione è ben noto, ma ciò che a volte manca è la comprensione di come verranno utilizzati i registri.

I requisiti di registrazione di ogni organizzazione sono unici e quindi anche la modalità di configurazione della registrazione di PostgreSQL sarà diversa. Ciò che una società di servizi finanziari deve acquisire all'interno dei registri del database sarà diverso da ciò che deve registrare un'azienda che si occupa di informazioni sanitarie critiche. E in alcuni casi possono anche essere simili.

In questo articolo tratterò alcune pratiche fondamentali per ottenere il meglio dai log di PostgreSQL. Questo blog non è un libro di regole rigido e veloce; i lettori sono più che benvenuti a condividere i loro pensieri nella sezione commenti. Per ottenere il miglior valore da esso, però, chiedo al lettore di pensare a come vogliono utilizzare i log del server di database PostgreSQL:

  • Motivo di conformità legale per cui è necessario acquisire informazioni specifiche
  • Controllo di sicurezza dove devono essere presenti dettagli di eventi specifici
  • Risoluzione dei problemi relativi alle prestazioni in cui devono essere registrate le query e i relativi parametri
  • Supporto operativo quotidiano in cui è necessario monitorare un determinato numero di metriche

Detto questo, iniziamo.

Non apportare modifiche manuali a postgresql.conf

Eventuali modifiche al file postgresql.conf devono essere apportate utilizzando un sistema di gestione della configurazione come Puppet, Ansible o Chef. Ciò garantisce che le modifiche siano tracciabili e possano essere ripristinate in sicurezza a una versione precedente, se necessario. Ciò vale quando si apportano modifiche ai parametri di registrazione.

I DBA spesso creano più copie del file postgresql.conf, ciascuna con parametri leggermente diversi, ciascuna per uno scopo diverso. La gestione manuale di diversi file di configurazione è un compito ingombrante se non soggetto a errori. D'altra parte, è possibile creare un sistema di gestione della configurazione per rinominare e utilizzare diverse versioni del file postgresql.conf in base a un parametro passato ad esso. Questo parametro determinerà lo scopo della versione corrente. Quando la necessità è completata, il vecchio file di configurazione può essere ripristinato modificando lo stesso parametro di input.

Ad esempio, se desideri registrare tutte le istruzioni in esecuzione sulla tua istanza PostgreSQL, è possibile utilizzare un file di configurazione con il valore del parametro "log_statement=all". Quando non è necessario registrare tutte le istruzioni, magari dopo un esercizio di risoluzione dei problemi, è possibile ripristinare il file di configurazione precedente.

Utilizza file di registro separati per PostgreSQL

Consiglio di abilitare il raccoglitore di registrazione nativo di PostgreSQL durante le normali operazioni. Per abilitare la registrazione nativa di PostgreSQL, imposta il seguente parametro su on:

logging_collector = on

Ci sono due ragioni per questo:

Prima di tutto, nei sistemi occupati, il sistema operativo potrebbe non registrare in modo coerente i messaggi PostgreSQL in syslog (supponendo un'installazione basata su nix) e spesso eliminare i messaggi. Con la registrazione nativa di PostgreSQL, un demone separato si occupa della registrazione degli eventi. Quando PostgreSQL è occupato, questo processo rinvia la scrittura sui file di registro per consentire ai thread di query di terminare. Questo può bloccare l'intero sistema fino a quando non viene scritto l'evento del registro. È quindi utile registrare nel log messaggi meno dettagliati (come vedremo più avanti) e utilizzare prefissi di log line abbreviati.

In secondo luogo, e come vedremo in seguito, i registri dovrebbero essere raccolti, analizzati, indicizzati e analizzati con un'utilità di gestione dei registri. Avere PostgreSQL che registra i suoi eventi in syslog significherà creare un ulteriore livello di filtraggio e corrispondenza dei modelli nella parte di gestione dei registri per filtrare tutti i "messaggi di disturbo". I file di registro dedicati possono essere facilmente analizzati e indicizzati per gli eventi dalla maggior parte degli strumenti.

Imposta la destinazione del registro su stderr

Consideriamo il parametro "log_destination". Può avere quattro valori:

log_destination = stderr | syslog | csv | eventlog

A meno che non vi sia una buona ragione per salvare gli eventi di registro in formato separato da virgole o il registro eventi in Windows, consiglio di impostare questo parametro su stderr. Questo perché con una destinazione di file CSV, un valore del parametro "log_line_prefix" personalizzato non avrà alcun effetto, eppure il prefisso può contenere informazioni preziose.

D'altra parte, tuttavia, un registro CSV può essere facilmente importato in una tabella di database e successivamente interrogato utilizzando SQL standard. Alcuni utenti di PostgreSQL lo trovano più conveniente rispetto alla gestione dei file di registro non elaborati. Come vedremo in seguito, le moderne soluzioni di gestione dei registri possono analizzare in modo nativo i registri PostgreSQL e creare automaticamente approfondimenti significativi da essi. Con CSV, il reporting e la visualizzazione devono essere eseguiti manualmente dall'utente.

Alla fine si tratta di una tua scelta. Se ti senti a tuo agio nel creare la tua pipeline di importazione dei dati per caricare i log CSV nelle tabelle del database, pulire e trasformare i dati e creare report personalizzati adatti alle tue esigenze aziendali, assicurati che "log_destination" sia impostato su CSV.

Utilizzare nomi di file di registro significativi

Quando i file di registro PostgreSQL vengono salvati localmente, seguire uno stile di denominazione potrebbe non sembrare necessario. Lo stile del nome file predefinito è "postgresql-%Y-%m-%d_%H%M%S.log" per i log non formattati CSV, che è sufficiente per la maggior parte dei casi.

La denominazione diventa importante quando si salvano file di registro da più server in una posizione centrale come un server di registro dedicato, un volume NFS montato o un bucket S3. Consiglio di utilizzare due parametri in questo caso:

log_directory
log_filename

Per archiviare file di registro da più istanze in un'unica posizione, crea innanzitutto una gerarchia di directory separata per ciascuna istanza. Può essere qualcosa di simile al seguente:

/<Application_Name>/<Environment_Name>/<Instance_Name>

La "directory_registro" di ogni istanza PostgreSQL può quindi essere indirizzata alla cartella designata.

Ciascuna istanza può quindi utilizzare lo stesso valore del parametro "log_filename". Il valore predefinito creerà un file come

postgresql_2020-08-25_2359.log

Per utilizzare un nome più significativo, imposta "log_filename" su qualcosa di simile a questo:

log_filename = "postgresql_%A-%d-%B_%H%M"

I file di registro saranno quindi denominati come:

postgresql_sabato-23-agosto_2230

Utilizzare un prefisso di riga di registro significativo

I prefissi delle righe di registro di PostgreSQL possono contenere le informazioni più preziose oltre al messaggio stesso. La documentazione di Postgres mostra diversi caratteri di escape per la configurazione del prefisso degli eventi di registro. Queste sequenze di escape vengono sostituite con vari valori di stato in fase di esecuzione. Alcune applicazioni come pgBadger prevedono un prefisso di riga di registro specifico.

Consiglio di includere le seguenti informazioni nel prefisso:

  • L'ora dell'evento (senza millisecondi):%t
  • Nome client remoto o indirizzo IP:%h
  • Nome utente:%u
  • Accesso al database:%d
  • Nome dell'applicazione:%a
  • ID processo:%p
  • Uscita del processo non di sessione terminato:%q
  • Il numero della riga di registro per ogni sessione o processo, a partire da 1:%l

Per capire di cosa tratta ogni campo nel prefisso, possiamo aggiungere una piccola stringa letterale prima del campo. Quindi, il valore dell'ID processo può essere preceduto dal letterale "PID="", il nome del database può essere preceduto da "db=" ecc. Ecco un esempio:

log_line_prefix = 'time=%t, pid=%p %q db=%d, usr=%u, client=%h , app=%a, line=%l '

A seconda della provenienza dell'evento, il prefisso della riga di registro mostrerà valori diversi. Sia i processi in background che i processi utente registreranno i loro messaggi nel file di registro. Per i processi di sistema, ho specificato %q, che sopprimerà qualsiasi testo dopo l'ID processo (%p). Qualsiasi altra sessione mostrerà il nome del database, il nome utente, l'indirizzo del client, il nome dell'applicazione e una riga numerata per ogni evento.

Inoltre, ho incluso un singolo spazio dopo il prefisso della riga di registro. Questo spazio separa il prefisso dell'evento del registro dal messaggio dell'evento effettivo. Non deve essere necessariamente uno spazio:è possibile utilizzare qualsiasi cosa come un doppio due punti (::), un trattino (-) o un altro separatore significativo.

Inoltre, imposta il parametro "log_hostname" su 1:

log_hostname = 1

Senza questo, verrà mostrato solo l'indirizzo IP del client. Nei sistemi di produzione, questo sarà in genere l'indirizzo del proxy, del servizio di bilanciamento del carico o del pool di connessioni. A meno che tu non conosca a memoria gli indirizzi IP di questi sistemi, potrebbe essere utile registrare i loro nomi host. Tuttavia, la ricerca DNS aggiungerà anche più tempo per il demone di registrazione per scrivere nel file.

Un altro parametro che dovrebbe essere impostato insieme a "log_line_prefix" è "log_timezone". L'impostazione del fuso orario locale del server garantirà che gli eventi registrati siano facili da seguire dal loro timestamp invece di convertirli prima nell'ora locale. Nello snippet di codice riportato di seguito, impostiamo log_timzeone sul fuso orario standard dell'Australia orientale:

log_timezone = 'Australia/Sydney'

Registra solo connessioni

Due parametri controllano il modo in cui PostgreSQL registra le connessioni e le disconnessioni dei client. Entrambi i parametri sono disattivati ​​per impostazione predefinita. In base ai requisiti di sicurezza della tua organizzazione, potresti voler impostare uno di questi su 1 e l'altro su 0 (a meno che tu non stia utilizzando uno strumento come pgBadger, ne parleremo più avanti).

log_connections = 1
log_disconnections = 0

L'impostazione di log_connections su 1 registrerà tutte le connessioni autorizzate e tentati connessioni. Questo è ovviamente un bene per il controllo della sicurezza:un attacco di forza bruta può essere facilmente identificato dai log. Tuttavia, con questa impostazione abilitata, un ambiente PostgreSQL occupato con migliaia o addirittura centinaia di connessioni valide di breve durata potrebbe vedere il file di registro essere inondato.

Tuttavia, può anche identificare problemi applicativi che potrebbero non essere ovvi altrimenti. Un numero elevato di tentativi di connessione da molti indirizzi client validi diversi può indicare che l'istanza necessita di un servizio di bilanciamento del carico o di pool di connessioni davanti a sé. Un numero elevato di tentativi di connessione da un singolo indirizzo client potrebbe scoprire un'applicazione con troppi thread che richiedono un qualche tipo di limitazione.

Registra solo operazioni DDL e DML

C'è molto dibattito su cosa dovrebbe essere registrato nel registro di Postgres, ovvero quale dovrebbe essere il valore del parametro "log_statement". Può avere tre valori:

log_statement = 'off' | 'ddl' | 'mod' | 'all'

Potrebbe essere allettante impostarlo su "tutto" per acquisire ogni istruzione SQL in esecuzione sul server, ma in realtà potrebbe non essere sempre una buona idea.

I sistemi di produzione occupati eseguono principalmente istruzioni SELECT, a volte migliaia all'ora. L'istanza potrebbe funzionare perfettamente, senza problemi di prestazioni. L'impostazione di questo parametro su "tutti" in questi casi appesantirebbe inutilmente il demone di registrazione poiché deve scrivere tutte quelle istruzioni nel file.

Ciò che si desidera acquisire, tuttavia, è qualsiasi danneggiamento dei dati o modifiche nella struttura del database che hanno causato qualche tipo di problema. Le modifiche al database indesiderate o non autorizzate causano più problemi dell'applicazione rispetto alla selezione dei dati; ecco perché consiglio di impostare questo parametro su "mod". Con questa impostazione, PostgreSQL registrerà tutte le modifiche DDL e DML nel file di registro.

Se la tua istanza PostgreSQL è moderatamente occupata (dozzine di query all'ora), sentiti libero di impostare questo parametro su "tutti". Quando si esegue la risoluzione dei problemi di query SELECT a esecuzione lenta o si cerca l'accesso ai dati non autorizzato, è anche possibile impostarlo temporaneamente su "tutti". Alcune applicazioni come pgBadger si aspettano anche che tu lo imposti su "tutti".

Registra i messaggi di "Avviso" e oltre

Se il parametro "log_statement" decide quale tipo di istruzioni verranno registrate, i due parametri seguenti determinano quanto sarà dettagliato il messaggio:

log_min_messages
log_min_error_statement

Ogni evento PostgreSQL ha un livello di messaggio associato. Il livello del messaggio può essere qualsiasi cosa, da DEBUG dettagliato a PANIC conciso. Più basso è il livello, più dettagliato è il messaggio. Il valore predefinito per il parametro “log_min_messages” è “WARNING”. Ti consiglio di mantenerlo a questo livello a meno che tu non voglia che anche i messaggi informativi vengano registrati.

Il parametro "log_min_error_statement" controlla quali istruzioni SQL che generano errori verranno registrate. Come "log_min_message", verrà registrata qualsiasi istruzione SQL con un livello di gravità dell'errore uguale o superiore al valore specificato in "log_min_error_statement". Il valore predefinito è "ERRORE" e consiglio di mantenere il valore predefinito.

Mantieni i parametri della durata del registro sui valori predefiniti

Quindi abbiamo i seguenti due parametri:

log_duration
log_min_duration_statement

Il parametro "log_duration" assume un valore booleano. Quando è impostato su 1, verrà registrata la durata di ogni istruzione completata. Se impostato su 0, la durata dell'istruzione non verrà registrata. Questo è il valore predefinito e consiglio di mantenerlo su 0 a meno che non si stiano risolvendo problemi di prestazioni. Il calcolo e la registrazione della durata delle istruzioni fa sì che il motore di database faccia un lavoro extra (non importa quanto piccolo) e quando viene estrapolato a centinaia o migliaia di query, i risparmi possono essere significativi.

Infine, abbiamo il parametro "log_min_duration_statement". Quando questo parametro è impostato (senza alcuna unità, viene utilizzato in millisecondi), verrà registrata la durata di qualsiasi istruzione che duri uguale o superiore al valore del parametro. L'impostazione di questo valore di parametro su 0 registrerà la durata di tutte le istruzioni completate. L'impostazione su -1 disabiliterà la registrazione della durata dell'istruzione. Questo è il valore predefinito e ti consiglio di mantenerlo tale.

L'unica volta in cui si desidera impostare questo parametro su 0 è quando si desidera creare una previsione delle prestazioni per le query eseguite di frequente. Tieni presente, però, che se il parametro “log_statement” è impostato, le istruzioni che vengono registrate non verranno ripetute nei messaggi di log che mostrano le durate. Quindi dovrai caricare i file di registro in una tabella del database, quindi unire i valori Process ID e Session ID dai prefissi della riga di registro per identificare le istruzioni correlate e le relative durate.

Qualunque sia il mezzo, una volta che hai una linea di base per ogni query eseguita di frequente, puoi impostare il parametro "log_min_duration_statement" sul valore più alto della linea di base. Ora, qualsiasi query eseguita più a lungo del valore di base più alto sarà un candidato per la messa a punto.

Mantieni la verbosità dei messaggi di errore sui valori predefiniti

Il parametro “log_error_verbosity” può avere tre possibili valori:

log_error_verbosity = terse | standard | verbose

Questo parametro controlla la quantità di informazioni che PostgreSQL registrerà per ogni evento registrato nel file di registro. A meno che non si stia effettuando il debug di un'applicazione di database, è meglio mantenere questo parametro su "predefinito". La modalità dettagliata sarà utile quando è necessario acquisire il nome del file o della funzione e il numero di riga che ha generato l'errore. L'impostazione su "conciso" sopprimerà la registrazione della query, che potrebbe non essere utile.

Trova una politica di rotazione del registro che funzioni per tuo Caso d'uso

Consiglio di creare una politica di rotazione del registro basata sulla dimensione o sull'età del file di registro, ma non su entrambi. Due parametri di configurazione di PostgreSQL determinano come vengono archiviati i vecchi log e come vengono creati i nuovi log:

log_rotation_age = <number of minutes>
log_rotation_size = <number of kilobytes>

Il valore predefinito per "log_rotration_age" è 24 ore e il valore predefinito per "log_rotation_size" è 10 megabyte.

Nella maggior parte dei casi, avere una politica di rotazione delle dimensioni non garantisce sempre che l'ultimo messaggio di registro nel file di registro archiviato sia contenuto solo in quel file.

Se "log_rotation_age" viene mantenuto al suo valore predefinito di 24 ore, ogni file può essere facilmente identificato ed esaminato individualmente, poiché ogni file conterrà un giorno di eventi. Tuttavia, anche questo non garantisce che ogni file sarà un'unità autonoma di log delle ultime 24 ore. A volte una query con prestazioni lente può richiedere più di 24 ore per essere completata; eventi potrebbero verificarsi quando il vecchio file viene chiuso e viene generato quello nuovo. Questo può essere il caso durante un processo batch notturno, con il risultato che alcune parti delle query vengono registrate in un file e il resto in un altro.

Il nostro consiglio è di trovare un periodo di rotazione del registro che funzioni per il tuo caso d'uso. Controllare la differenza di orario tra due periodi consecutivi di attività più bassa (ad esempio tra un sabato e l'altro). È quindi possibile impostare il valore "log_rotation_age" su quella differenza di orario e, durante uno di questi periodi, riavviare il servizio PostgreSQL. In questo modo, PostgreSQL ruoterà il file di registro corrente quando si verifica il prossimo periodo di pausa. Tuttavia, se è necessario riavviare il servizio tra questi periodi, la rotazione del registro verrà nuovamente distorta. Dovrai quindi ripetere questo processo. Ma come per molte altre cose in PostgreSQL, tentativi ed errori determineranno il miglior valore. Inoltre, se stai utilizzando un'utilità di gestione dei registri, l'età o la dimensione della rotazione del registro non contano perché l'agente di gestione dei registri acquisirà ogni evento dal file non appena viene aggiunto.

Utilizza strumenti come pgBadger

pgBadger è un potente analizzatore di log PostgreSQL in grado di creare informazioni molto utili dai file di log di Postgres. È uno strumento open source scritto in Perl con un ingombro molto ridotto nella macchina in cui viene eseguito. Lo strumento viene eseguito dalla riga di comando e viene fornito con un gran numero di opzioni. Prenderà uno o più log come input e può produrre un report HTML con statistiche dettagliate su:

  • Query più frequenti.
  • Query che generano la maggior parte dei file temporanei oi file temporanei più grandi
  • Query con esecuzione più lenta
  • Durata media della query
  • Query eseguite più frequentemente
  • Errori più frequenti nelle query
  • Utenti e applicazioni che eseguono query
  • Statistiche sui posti di blocco.
  • Autovacuum e analisi automatica delle statistiche.
  • Blocco delle statistiche
  • Eventi di errore (panico, fatale, errore e avviso).
  • Profili di connessione e sessione (per database, utente, applicazione)
  • Profili di sessione
  • Profili di query (tipi di query, query per database/applicazione)
  • Statistiche I/O
  • ecc.

Come accennato in precedenza, alcuni dei parametri di configurazione relativi al registro devono essere abilitati per acquisire tutti gli eventi del registro in modo che pgBadger possa analizzare efficacemente quei registri. Poiché ciò può produrre file di registro di grandi dimensioni con molti eventi, pgBadger dovrebbe essere utilizzato solo per creare benchmark o risolvere problemi di prestazioni. Una volta generati i registri dettagliati, i parametri di configurazione possono essere riportati ai valori originali. Per l'analisi continua dei registri, è meglio utilizzare un'applicazione di gestione dei registri dedicata.

Se sei più a tuo agio nel fare le cose nel prompt dei comandi e nell'usare le viste di sistema, dovresti usare pg_stat_statements. In effetti, questo dovrebbe essere abilitato in qualsiasi installazione di PostgreSQL di produzione.

pg_stat_statements è un'estensione PostgreSQL e ora con l'installazione predefinita. Per abilitarlo, il parametro di configurazione "shared_preload_libraries" dovrebbe avere pg_stat_statements come uno dei suoi valori. Può quindi essere installato come qualsiasi altra estensione utilizzando il comando "CREA ESTENSIONE". L'estensione crea la vista pg_stat_statement che fornisce preziose informazioni relative alle query.

Utilizzare un'applicazione di gestione dei registri per ottenere informazioni dettagliate

Esistono molte utilità di gestione dei registri sul mercato e la maggior parte delle organizzazioni ne utilizza una o più al giorno d'oggi. Qualunque sia lo strumento in atto, consiglio di utilizzarlo per raccogliere e gestire i log di PostgreSQL.

Ci sono alcune ragioni per questo:

È molto più semplice analizzare, analizzare e filtrare il rumore dai file di registro con uno strumento automatizzato. A volte, un evento può estendersi su più file di registro in base alla durata dell'evento e all'età o alle dimensioni della rotazione del registro. Avere un log manager rende molto più semplice presentare queste informazioni nel loro insieme.

Le soluzioni di gestione dei log oggigiorno in genere sono dotate della capacità integrata di analizzare i log PostgreSQL. Alcuni sono inoltre dotati di dashboard in grado di mostrare le metriche più comuni estratte da questi log.

La maggior parte delle moderne applicazioni di gestione dei registri offre anche potenti funzionalità di ricerca, filtro, corrispondenza dei modelli, correlazione degli eventi e analisi delle tendenze abilitate dall'intelligenza artificiale. Ciò che non è visibile agli occhi comuni può essere facilmente reso evidente da questi strumenti.

Infine, l'utilizzo di un log manager per archiviare i log di PostgreSQL significherà anche che gli eventi verranno salvati per i posteri, anche se i file originali vengono eliminati accidentalmente o intenzionalmente.

Sebbene ci siano ovvi vantaggi nell'utilizzo di un'applicazione di gestione dei registri, molte organizzazioni hanno restrizioni su dove i loro registri possono vivere. Questo è un caso tipico con le soluzioni basate su SaaS in cui i registri vengono spesso salvati al di fuori del confine geografico di un'organizzazione, cosa che potrebbe non essere conforme ai requisiti normativi.

In questi casi, consiglio di scegliere un fornitore con presenza di un data center locale, se possibile, o di utilizzare un log manager autogestito ospitato nella rete dell'organizzazione, ad esempio uno stack ELK.

Le ultime parole

I log del server PostgreSQL possono essere una miniera d'oro di informazioni se opportunamente configurati. Il trucco è determinare cosa registrare e quanto registrare e, soprattutto, verificare se i registri possono fornire le informazioni corrette quando necessario. Sarà una questione di tentativi ed errori, ma quello che ho discusso qui oggi dovrebbe dare un inizio abbastanza decente. Come ho detto all'inizio, sarei più che felice di conoscere la tua esperienza nella configurazione del logging di PostgreSQL per risultati ottimali.