La gestione dei database non è un compito da poco e può essere facilmente frustrante senza sapere cosa sta succedendo sotto le coperte. Sia che si cerchi di scoprire se i nuovi indici sono utili, il conteggio delle transazioni su un database in un determinato momento o chi è connesso al database in un dato momento, i dati che consentono agli amministratori di sapere veramente come stanno andando i loro database sono il re. Fortunatamente, con PostgreSQL, i dati per tutto questo sono disponibili nel catalogo di sistema di PostgreSQL.
Il Catalogo di sistema PostgreSQL è uno schema con tabelle e viste che contengono metadati su tutti gli altri oggetti all'interno del database e altro ancora. Con esso, possiamo scoprire quando si verificano varie operazioni, come si accede a tabelle o indici e anche se il sistema di database sta leggendo informazioni dalla memoria o ha bisogno di recuperare dati dal disco.
Qui esamineremo una panoramica del catalogo di sistema ed evidenzieremo come leggerlo e come estrarne informazioni utili. Alcuni dei metadati sono semplici e altri pezzi richiedono un po' di digestione per generare informazioni davvero utili. In ogni caso, PostgreSQL ci offre un'ottima piattaforma per creare qualsiasi informazione di cui abbiamo bisogno sul database stesso.
Il catalogo PostgreSQL
PostgreSQL memorizza le informazioni sui metadati sul database e sul cluster nello schema 'pg_catalog'. Queste informazioni sono parzialmente utilizzate dallo stesso PostgreSQL per tenere traccia delle cose stesse, ma vengono anche presentate in modo che anche le persone/processi esterni possano comprendere l'interno dei database.
Il Catalogo PostgreSQL ha una regola piuttosto solida:guarda, non toccare. Sebbene PostgreSQL memorizzi tutte queste informazioni nelle tabelle come farebbe qualsiasi altra applicazione, i dati nelle tabelle sono completamente gestiti da PostgreSQL stesso e non dovrebbero essere modificati a meno che non sia un'emergenza assoluta, e anche in questo caso è probabile una ricostruzione in ordine in seguito.
Esamineremo alcune utili tabelle di catalogo, come leggere i dati e cose intelligenti che possiamo fare con i dati stessi. Ci sono alcune tabelle nel catalogo che non esamineremo, ma tutte le informazioni per queste varie tabelle possono essere trovate nella documentazione ufficiale di PostgreSQL.
Metadati a livello di sistema
Una buona parte delle tabelle che possiamo interrogare nel catalogo sono tabelle "a livello di sistema", dove non importa a quale database siamo collegati, i dati rappresentano l'intero cluster, nessun database singolo.
Informazioni sul database
Le informazioni generali sul database sono archiviate in pg_database e le statistiche sono archiviate in pg_stat_database.
pg_database:
postgres=# SELECT oid,* FROM pg_database WHERE datname = 'severalnines';
-[ RECORD 1 ]-+-------------
oid | 16396
datname | severalnines
datdba | 10
encoding | 6
datcollate | en_US.UTF-8
datctype | en_US.UTF-8
datistemplate | f
datallowconn | t
datconnlimit | -1
datlastsysoid | 13804
datfrozenxid | 548
datminmxid | 1
dattablespace | 1663
datacl |
La tabella pg_database contiene una riga per ogni database nel cluster, inclusi i tre che escono dalla scatola (postgres, template0 e template1). Questa riga contiene informazioni per la codifica, il limite di connessione e altri metadati di base.
Colonne di interesse:
oid - L'identificatore dell'oggetto, che non viene visualizzato nell'output di una query a meno che non venga fatto riferimento direttamente. Questo numero corrisponderà a una directory nella directory dei dati del cluster
datname - Il nome del database.
datdba - Il proprietario del database, oid fa riferimento a pg_authid .oid.
encoding - La codifica dei caratteri per questo database, pg_encoding_to_char() verrà convertita in un nome leggibile.
datconnlimit - Il numero massimo di connessioni simultanee consentite sul database.
dattablespace - Il tablespace di default per questo database, fa riferimento a pg_tablespace.oid.
pg_stat_database:
postgres=# SELECT * FROM pg_stat_database WHERE datname = 'severalnines';
-[ RECORD 1 ]--+------------------------------
datid | 13805
datname | postgres
numbackends | 2
xact_commit | 477460
xact_rollback | 13
blks_read | 417
blks_hit | 16488702
tup_returned | 252376522
tup_fetched | 2637123
tup_inserted | 114
tup_updated | 3
tup_deleted | 1
conflicts | 0
temp_files | 0
temp_bytes | 0
deadlocks | 0
blk_read_time | 0
blk_write_time | 0
stats_reset | 2018-02-04 19:52:39.129052+00
Questa tabella delle statistiche è dove otteniamo dati interessanti e utili. Ogni riga di questa tabella contiene dati in tempo reale per ogni database e può essere esportata periodicamente per essere monitorata nel tempo se si desidera monitorare le modifiche.
Transazioni
Le informazioni sulle transazioni possono essere trovate nelle colonne xact_commit e xact_rollback, che contengono rispettivamente il numero di transazioni di cui il database ha eseguito il commit e il rollback. Questo aiuterà a mostrare quanto sia attivo un database, oltre a individuare possibili errori con i programmi che potrebbero essere in errore/ripristino a una velocità allarmante.
Accesso al disco e alla memoria
Le informazioni sul recupero o meno dei dati dal disco o dalla memoria sono archiviate nelle colonne blks_read e blks_hit. Blks_read mostra il numero di blocchi letti da questo database dal disco, mentre blks_hit mostra il numero di blocchi che sono stati trovati nella cache del buffer di PostgreSQL (rappresentato dal parametro shared_buffers). Poiché la RAM è molto più veloce del disco, idealmente vedremmo blks_hit costantemente superiore a blks_read e, in caso contrario, possiamo rivalutare la nostra memoria disponibile.
Tuple
Le prossime colonne trattano di tuple. Tup_returned è il numero di righe restituite nel database, che è il numero di righe lette da scansioni sequenziali se da una tabella, o il numero di voci di indice restituite da un indice”. Tup_fetched è il numero di righe recuperate nel database, il che significa che erano il risultato di scansioni bitmap, che è il numero di righe di tabella recuperate da scansioni bitmap se da una tabella o righe di tabella recuperate da scansioni di indici semplici se si utilizza un indice.
Abbiamo anche tup_inserted, tup_updated e tup_deleted, che rappresentano rispettivamente il numero di tuple inserite, aggiornate ed eliminate in questo database. Questo aiuterà a capire come i dati entrano, cambiano e lasciano il database. Poiché le tuple aggiornate ed eliminate generano righe morte, valori elevati in queste colonne suggeriscono che le operazioni di autovacuum siano ottimizzate per soddisfare le esigenze dell'attività del database.
Conflitti
Se il database in questione è un server in standby, i conflitti di colonna sono utili per tenere traccia di quante query sono state annullate a causa di conflitti con lo standby in "modalità di ripristino". Se non è un cluster in standby, questa colonna può essere ignorata.
File/dati temporanei
A volte, le query dovranno essere scritte su file temporanei. Ciò può verificarsi quando la quantità di work_mem allocata alla connessione è stata esaurita e deve continuare un'operazione di ordinamento su disco anziché in memoria. La colonna temp_files tiene traccia del numero di questi file che sono stati creati e temp_bytes tiene traccia della dimensione totale di tutti i file temporanei utilizzati. Questi dati possono aiutare a informare l'ottimizzazione di work_mem o persino a trovare query che potrebbero richiedere la riscrittura se le dimensioni del file temporaneo sono troppo grandi.
Deadlock
La colonna deadlock tiene traccia di quante volte si verifica un deadlock. Poiché un deadlock può causare errori per query che altrimenti non comporterebbero errori, è bene tenerne traccia e assicurarsi che le applicazioni non si calpestino a vicenda.
Tempi di lettura e scrittura
Le colonne blk_read_time e blk_write_time tengono traccia del numero totale di millisecondi che i backend nel database trascorrono a leggere e scrivere dati, il che può essere utile se si cerca di confrontare/migliorare la velocità di lettura/scrittura del disco
Statistiche ripristinate
Questa colonna, stats_reset, mostra semplicemente un timestamp (con fuso orario) dell'ultima volta che le statistiche menzionate in questa riga sono state reimpostate. Un valore nullo significa che non sono stati reimpostati dall'inizio, o anche forse un arresto anomalo del database che potrebbe aver cancellato queste statistiche.
I checkpoint e lo scrittore in background
pg_stat_bgwriter
postgres=# SELECT * FROM pg_stat_bgwriter;
-[ RECORD 1 ]---------+------------------------------
checkpoints_timed | 47829
checkpoints_req | 2
checkpoint_write_time | 7323
checkpoint_sync_time | 38
buffers_checkpoint | 76
buffers_clean | 0
maxwritten_clean | 0
buffers_backend | 5
buffers_backend_fsync | 0
buffers_alloc | 440
stats_reset | 2018-02-04 19:52:34.712832+00
Il cluster PostgtreSQL gestisce la scrittura dei dati su disco in diversi modi. In termini di "buffer sporchi" (dati in memoria che sono stati modificati da quando sono stati letti dal disco, ma non hanno ancora scritto la modifica sul disco), ciò viene fatto da un checkpoint o dallo scrittore in background. Poiché un buffer sporco deve essere scritto su disco prima che possa essere liberato o riallocato, assicurarsi che questi processi siano ottimizzati è fondamentale e questa tabella aiuta a far luce su come funziona.
Punti di controllo
Un checkpoint si verifica nei tempi previsti (rappresentato dal parametro checkpoint_timeout) o quando è stata utilizzata la quantità massima di file WAL dall'ultimo checkpoint e deve forzare un checkpoint. In ogni caso, un checkpoint scrive buffer sporchi su disco e ci sono quattro colonne che lo tengono traccia.
Le colonne checkpoints_timed e checkpoints_req mostrano il numero di checkpoint programmati (a tempo) e il numero di checkpoint richiesti (indicati anche come forzati). Un valore di salita elevato di checkpoint_req potrebbe suggerire un valore max_wal_size insufficiente.
Le colonne checkpoint_write_time e checkpoint_sync_time registrano la quantità di tempo totale (in millisecondi) che il processo di checkpoint ha impiegato per scrivere e sincronizzare su disco.
Infine, buffers_checkpoint è il numero totale di buffer scritti su disco dai checkpoint.
Scrittore di sfondo
Il writer in background è un processo separato che scrive i buffer sporchi sul disco, riducendo idealmente la quantità di lavoro che deve eseguire il checkpointer.
La colonna buffers_clean rappresenta il numero di buffer scritti su disco dal processo in background. Rispetto a buffers_checkpoint, mostra quanto carico di lavoro viene gestito da ciascun processo (con la consapevolezza in più che lo scrittore in background ha la possibilità di scrivere buffer più volte se cambiano spesso, rispetto a meno frequentemente con un checkpoint a tempo).
Maxwrite_clean rappresenta il numero di volte in cui lo scrittore in background ha raggiunto il numero massimo di pagine da svuotare ogni volta che viene eseguito (controllato con il parametro bgwriter_lru_maxpages).
Buffer in generale
Le colonne rimanenti ci mostrano le informazioni generali sul buffer, con buffers_backend che è il numero di buffer che un backend ha dovuto scrivere da solo, invece di writer in background o checkpointer, buffers_backend_fsync è un conteggio di quante volte un backend ha dovuto eseguire la propria chiamata fsync e buffers_alloc mostra il numero di buffer che sono stati allocati in generale.
Attività del database e blocchi
Ci sono due viste che mostrano l'attività corrente dell'utente, pg_stat_activity e pg_locks. Quando interrogati, mostrano informazioni sulle connessioni correnti ai database e sul tipo di blocchi che hanno su quali relazioni.
pg_stat_attività
postgres=# SELECT * FROM pg_stat_activity;
-[ RECORD 1 ]----+--------------------------------
datid | 13805
datname | severalnines
pid | 29730
usesysid | 10
usename | postgres
application_name | psql
client_addr |
client_hostname |
client_port | -1
backend_start | 2018-07-21 02:29:48.976588+00
xact_start | 2018-07-21 02:30:03.73683+00
query_start | 2018-07-21 02:30:03.73683+00
state_change | 2018-07-21 02:30:03.736835+00
wait_event_type |
wait_event |
state | active
backend_xid |
backend_xmin | 559
query | SELECT first_name FROM customers WHERE customers_sid = 472;
backend_type | client backend
Informazioni generali
La vista pg_stat_activity mostra una riga per ogni connessione al database e alcune informazioni di base su di esso. La colonna datname rappresenta il database a cui è effettivamente connessa la connessione, pid è l'ID di processo della connessione sull'host del database stesso e usesysid e usename rappresentano l'utente del database connesso.
Per l'origine del client, client_addr è l'indirizzo IP dell'host da cui proviene la connessione, null significa che è una connessione socket unix locale.
Data e ora
Ci sono quattro colonne timestamp che mostrano quando alcune cose sono iniziate:backend_start è quando è stata effettivamente stabilita la connessione, xact_start è quando è iniziata la transazione corrente (null se il client non ha transazione aperta), query_start è quando è iniziata la query corrente o più recente, e state_change è l'ora in cui lo stato della connessione è cambiato per l'ultima volta.
Stato connessione
I bit finali di pg_stat_activity coprono lo stato effettivo della connessione. Se la query è in attesa che un altro rilasci i blocchi, wait_event_type contiene alcune informazioni sul tipo di evento wait e la colonna wait_event mostrerà il nome dell'evento wait. È una lunga lista, ma maggiori informazioni si trovano nella documentazione di PostgreSQL.
Infine, la colonna "stato" mostra lo stato in cui si trova la connessione corrente, ad esempio attiva, inattiva, inattiva in transazione, e la colonna della query mostrerà la query effettiva in esecuzione o eseguita più di recente.
pg_lock
SELECT * FROM pg_locks;
-[ RECORD 1 ]------+----------------
locktype | virtualxid
database |
relation |
page |
tuple |
virtualxid | 3/475862
transactionid |
classid |
objid |
objsubid |
virtualtransaction | 3/475862
pid | 29730
mode | ExclusiveLock
granted | t
fastpath | t
La tabella pg_locks funziona di pari passo con pg_stat_activity se si esamina l'attività di query. Ogni volta che viene eseguito un blocco su una relazione, tali informazioni vengono archiviate in pg_locks. Usando il pid di pg_stat_activity, possiamo interrogare pg_locks per vedere su quali relazioni una connessione può avere dei lock, che tipo di lock sono e se i lock sono stati concessi o meno.
Le colonne più importanti sono 'pid', che corrisponde al pid di pg_stat_activity, 'relation' che corrisponde all'OID di pg_class, 'mode' che mostra il nome della modalità di blocco mantenuta e 'concessa' che indica se il blocco in la domanda è stata accolta.
Informazioni sulla replica
Poiché PostgreSQL ha integrato funzionalità di replica, ci sono alcune viste che fanno luce sulle prestazioni e sullo stato della replica stessa.
Visualizza pg_stat_replication: contiene una riga per ogni processo mittente WAL, contenente informazioni sul suo stato, la posizione dei file WAL su cui sta lavorando e le informazioni sulla connessione dell'host in standby che sta ricevendo i dati WAL per la replica.
Visualizza pg_stat_wal_receiver: Se il cluster è in standby, questo conterrà una singola riga che mostra le statistiche sul processo di ricezione dall'host.
Visualizza pg_stat_subscription: Se si inviano dati WAL a un nodo di standby, ogni riga qui rappresenterà quella sottoscrizione e conterrà informazioni sullo stato delle sottoscrizioni.
Visualizza pg_replication_slots: Contiene un elenco di tutti gli slot di replica esistenti nel cluster e il loro stato corrente.
Metadati specifici del database
All'interno di ogni database è presente una raccolta di tabelle di catalogo che contengono informazioni specifiche per il database che viene interrogato. Se stiamo cercando dati specifici da queste tabelle, dobbiamo assicurarci di essere collegati al database corretto mentre emettiamo le query.
È qui che entra in gioco il cuore dell'analisi dei dati, dove possiamo vedere come viene effettuato l'accesso ai dati dei nostri utenti. Dalle tabelle, agli indici, alle sequenze, le query che entrano nel database e recuperano o modificano i dati, le loro azioni e il loro impatto verranno archiviati in queste tabelle e possiamo esaminare tali informazioni per prendere decisioni informate sulla gestione del database strada.
Metadati tabella
I metadati sulle nostre tabelle utente sono archiviati nelle due tabelle seguenti e ciascuna ha una riga per ogni tabella utente creata nel sistema. La tabella pg_stat_user_tables contiene le statistiche sull'accesso degli utenti alla tabella, mentre pg_statio_user_tables contiene le statistiche di I/O per ciascuna tabella.
NOTA:i dati qui contenuti non sono sempre perfetti al 100% e per essere corretti si basano su frequenti analisi delle tabelle. Autoanalyze copre questo, ma una buona messa a punto del processo di analisi automatica in modo che possa mantenere buone statistiche su ciascuna tabella. Se le statistiche sembrano essere disattivate, l'esecuzione manuale di ANALISI sulla tabella le aggiornerà.
Tabella pg_stat_user_tables:
severalnines=> SELECT * FROM pg_stat_user_tables WHERE schemaname = 'public' AND relname = 'history';
-[ RECORD 1 ]-------+---------
relid | 2766788
schemaname | public
relname | history
seq_scan | 13817
seq_tup_read | 466841
idx_scan | 12251
idx_tup_fetch | 127652
n_tup_ins | 11
n_tup_upd | 13
n_tup_del | 3
n_tup_hot_upd | 13
n_live_tup | 3
n_dead_tup | 21
n_mod_since_analyze | 19
last_vacuum |
last_autovacuum |
last_analyze |
last_autoanalyze |
vacuum_count | 0
autovacuum_count | 0
analyze_count | 0
autoanalyze_count | 0
Per le statistiche della nostra tabella utente, abbiamo un bel po' di dati.
Metodi di accesso alla tabella
Quando i client accedono ai dati dalla tabella, lo fa direttamente o tramite gli indici. La colonna "seq_scan" conta il numero di scansioni sequenziali ricevute dalla tabella e "seq_tup_read" conta il numero di tuple lette durante quel processo. La colonna "idx_scan" conta quante volte un indice nella tabella è stato utilizzato per recuperare i dati.
Attività tupla tabella
Ora abbiamo una manciata di colonne che contano diverse attività sulla tabella.
'n_tup_ins' tiene traccia del numero di tuple inserite
'n_tup_upd' tiene traccia del numero di tuple aggiornate
'n_tup_del' tiene traccia del numero di tuple eliminate
Stato tupla tabella
A causa di aggiornamenti ed eliminazioni, potrebbero esserci tuple morte che non sono più dati attivi e il processo di vuoto alla fine le libererà. Le colonne 'n_tup_ins' e 'n_tup_ins' tengono traccia del numero di tuple che sono rispettivamente vive e morte. Quando le tuple morte raggiungono un certo punto, verrà avviato un autovacuum, a seconda delle impostazioni dell'autovacuum.
Attività sottovuoto da tavolo
La manutenzione della tabella viene eseguita tramite VACUUM o AUTOVACUUM e le statistiche vengono raccolte tramite ANALYZE o AUTOANALYZE. Le quattro colonne successive contengono le date dell'ultima esecuzione di ciascuna di queste operazioni:"last_vacuum", "last_autovacuum", "last_analyze", "last_autoanalyze".
Abbiamo anche altre quattro comode colonne che contano semplicemente quante volte si verificano le azioni precedenti. Utilizzando questi, possiamo vedere quali tabelle ottengono più attività:"vacuum_count", "autovacuum_count", "analyze_count" e "autoanalyze_count".
Tabella pg_statio_user_tables:
severalnines=> SELECT * FROM pg_statio_user_tables WHERE schemaname = 'public' AND relname = history;
-[ RECORD 1 ]---+---------
relid | 2766788
schemaname | public
relname | history
heap_blks_read | 4
heap_blks_hit | 63081
idx_blks_read | 5
idx_blks_hit | 44147
toast_blks_read | 0
toast_blks_hit | 0
tidx_blks_read | 0
tidx_blks_hit | 0
L'uscita I/O è utile per aiutare a capire come si accede ai dati sotto le coperte. La colonna "heap_blks_read" rappresenta il numero di blocchi del disco letti per questa tabella e "heap_blks_hit" rappresenta i blocchi del buffer letti dalla memoria su questa tabella. Questo è utile per sapere se le query che accedono alla tabella devono andare costantemente su disco o recuperare i dati dalla memoria.
Le statistiche dell'indice sulla tabella mostrano le stesse informazioni con le colonne "idx_blks_read" e "idx_blks_hit".
Infine, se la tabella ha tabelle TOAST, le colonne "toast_blks_hit" e "toast_blks_read" tengono traccia delle tabelle toast, mentre "tdix_blks_read" e "tdix_blks_read" tengono traccia degli indici su quelle tabelle toast.
Metadati dell'indice
pg_stat_user_indexes
severalnines=> SELECT * FROM pg_stat_user_indexes WHERE indexrelname = 'history_pkey';
-[ RECORD 1 ]-+-------------
relid | 2766797
indexrelid | 2766934
schemaname | public
relname | history
indexrelname | history_pkey
idx_scan | 43910
idx_tup_read | 98147
idx_tup_fetch | 98147
Proprio come le controparti della tabella, questa tabella contiene informazioni sugli indici in particolare. Una riga per indice, questa tabella mostra quante volte l'indice è stato scansionato con la colonna "idx_scan", quante tuple sono state lette con "idx_tup_read" e quante righe live sono state effettivamente recuperate con "idx_tup_fetch".
pg_statio_user_indexes
severalnines=> SELECT * FROM pg_statio_user_indexes WHERE indexrelname = 'history_pkey';
-[ RECORD 1 ]-+-------------
relid | 2766797
indexrelid | 2766934
schemaname | public
relname | history
indexrelname | history_pkey
idx_blks_read | 2
idx_blks_hit | 49380
Per pg_statio_user_indexes, le due colonne disponibili per i dati sono 'idx_blks_read' e 'idx_blks_hit', che rappresentano il numero di blocchi letti dal disco e dalla memoria.
Scarica il whitepaper oggi Gestione e automazione di PostgreSQL con ClusterControlScopri cosa devi sapere per distribuire, monitorare, gestire e ridimensionare PostgreSQLScarica il whitepaperCosa possiamo fare con questi dati?
Diventa creativo! Se le query su una tabella specifica sembrano estremamente lente, monitora la sua attività nel tempo, guarda quante scansioni sequenziali ottiene rispetto alle scansioni dell'indice, controlla se i dati verranno trasferiti su disco o memoria.
Se una tabella di grandi dimensioni continua a essere sottoposta a svuotamento automatico frequentemente, monitora le tuple dal vivo a dead nel tempo, forse è necessario modificare specificamente l'autovacuum in modo che possa essere completato più rapidamente, o anche forse la tabella è un candidato per il partizionamento.
Dal momento che possiamo vedere quando i dati provengono dal disco o dalla memoria, possiamo creare un rapporto tra memoria e disco nel tempo, individuando se in qualsiasi momento il rapporto diminuisce nel corso della giornata.
La quantità di tabelle che abbiamo trattato è andata oltre i big hitter, i dati principali utili per conoscere il funzionamento interno dei database. Tuttavia ci sono molte più tabelle nel catalogo di sistema che contengono dati utili per la situazione. La lettura di altre tabelle come prima aiuterà a fornire approfondimenti sullo stato di salute del database in generale.
Per ulteriori informazioni su tabelle o viste nel Catalogo PostgreSQL, visita la documentazione ufficiale qui, così come le informazioni sul raccoglitore di statistiche qui.