Postmaster utilizza eccessive CPU e scritture su disco


9

usando PostgreSQL 9.1.2

Vedo un uso eccessivo della CPU e grandi quantità di scritture su disco da attività postmaster. Questo succede anche mentre la mia applicazione non fa quasi nulla (10s di inserti al MINUTO). Vi è tuttavia un numero ragionevole di connessioni aperte.

Ho cercato di determinare cosa sta causando nella mia applicazione. Sono abbastanza newb con postgresql e finora non sono arrivato da nessuna parte. Ho attivato alcune opzioni di registrazione nel mio file di configurazione e ho esaminato le connessioni nella tabella pg_stat_activity, ma sono tutte inattive. Tuttavia ogni connessione consuma ~ 50% di CPU e scrive ~ 15M / s sul disco (non legge nulla).

Sto fondamentalmente usando lo stock postgresql.conf con pochissime modifiche. Apprezzerei qualsiasi consiglio o suggerimento su cosa posso fare per rintracciarlo.

Ecco un esempio di ciò che top / iotop mi sta mostrando:

Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                          
17057 postgres  20   0  236m  33m  13m R 45.0  0.1  73:48.78 postmaster                                                                                                                       
17188 postgres  20   0  219m  15m  11m R 42.3  0.0  61:45.57 postmaster                                                                                                                       
17963 postgres  20   0  219m  16m  11m R 42.3  0.1  27:15.01 postmaster                                                                                                                       
17084 postgres  20   0  219m  15m  11m S 41.7  0.0  63:13.64 postmaster                                                                                                                       
17964 postgres  20   0  219m  17m  12m R 41.7  0.1  27:23.28 postmaster                                                                                                                       
18688 postgres  20   0  219m  15m  11m R 41.3  0.0  63:46.81 postmaster                                                                                                                       
17088 postgres  20   0  226m  24m  12m R 41.0  0.1  64:39.63 postmaster                                                                                                                       
24767 postgres  20   0  219m  17m  12m R 41.0  0.1  24:39.24 postmaster                                                                                                                       
18660 postgres  20   0  219m  14m 9.9m S 40.7  0.0  60:51.52 postmaster                                                                                                                       
18664 postgres  20   0  218m  15m  11m S 40.7  0.0  61:39.61 postmaster                                                                                                                       
17962 postgres  20   0  222m  19m  11m S 40.3  0.1  11:48.79 postmaster                                                                                                                       
18671 postgres  20   0  219m  14m   9m S 39.4  0.0  60:53.21 postmaster                                                                                                                       
26168 postgres  20   0  219m  15m  10m S 38.4  0.0  59:04.55 postmaster  


Total DISK READ: 0.00 B/s | Total DISK WRITE: 195.97 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND                                                                                                                        
17962 be/4 postgres    0.00 B/s   14.83 M/s  0.00 %  0.25 % postgres: aggw aggw [local] idle
17084 be/4 postgres    0.00 B/s   15.53 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17963 be/4 postgres    0.00 B/s   15.00 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17188 be/4 postgres    0.00 B/s   14.80 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17964 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
18664 be/4 postgres    0.00 B/s   15.13 M/s  0.00 %  0.23 % postgres: aggw aggw [local] idle
17088 be/4 postgres    0.00 B/s   14.71 M/s  0.00 %  0.13 % postgres: aggw aggw [local] idle
18688 be/4 postgres    0.00 B/s   14.72 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
24767 be/4 postgres    0.00 B/s   14.93 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18671 be/4 postgres    0.00 B/s   16.14 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
17057 be/4 postgres    0.00 B/s   13.58 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
26168 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18660 be/4 postgres    0.00 B/s   15.85 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle

Aggiornamento : gran parte della scrittura dei file sembra essere in alcuni file temporanei (?) Nella directory $ PG_DATA / base /. La mia comprensione della struttura dei file qui è che ogni tabella è sostanzialmente memorizzata come un file il cui nome è l'OID della tabella. Tuttavia, ci sono tonnellate di file denominati tnn_nnnnnnn, e sono questi file che sembrano essere scritti (forse sovrascritti) costantemente. A cosa servono questi file? Sono presenti circa 4700 file e tutti hanno una dimensione di 8 KB:

-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t12_1430975
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t16_1432736
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439066
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436243
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436210
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t19_1393372
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439051
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t8_1430334

Aggiornamento : l'esecuzione di strace sui processi postmaster mostra sostanzialmente molte cose di I / O dei file:

open("base/16388/t24_1435947_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
ftruncate(9, 0)                         = 0
lseek(9, 0, SEEK_END)                   = 0
open("base/16388/t24_1435941", O_RDWR)  = 18
lseek(18, 0, SEEK_END)                  = 0
write(9, "\0\0\0\0\0\0\0\0\1\0\0\0000\0\360\37\360\37\4 \0\0\0\0b1\5\0\2\0\0\0"..., 8192) = 8192
lseek(18, 0, SEEK_END)                  = 0
close(9)                                = 0
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
close(18)                               = 0
close(9)                                = 0
open("base/16388/t24_1435944_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435944_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435944", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 0
close(9)                                = 0

Aggiornamento : quindi questo problema sembra essere tutto a che fare con le tabelle temporanee. Abbiamo modificato la nostra configurazione in modo che le tabelle temporanee siano tabelle 'regolari' e tutte le attività del disco siano andate via e le prestazioni sono tornate dove mi aspettavo. Ora, questo cambiamento è stato solo un test rapido e sporco: se avremo davvero intenzione di cambiare per usare le tabelle regolari, avremo problemi con la concorrenza e la pulizia. I tavoli temporanei sono davvero così malvagi o li stiamo abusando?

Aggiornamento : qualche altro sfondo. Sto facendo uso di un middleware di replica basato su istruzioni sviluppato internamente . È abbastanza maturo ed è stato utilizzato su numerosi progetti per diversi anni, ma usando MySQL. Abbiamo lavorato con PostgreSQL solo negli ultimi due anni. Stavamo essenzialmente utilizzando le tabelle temporanee come parte del meccanismo di replica. Ogni volta che viene stabilita una nuova connessione, creiamo una tabella temporanea per ogni tabella nel database. Con 10-20 connessioni (di lunga durata) e ~ 50 tabelle, ciò può equivalere a molte tabelle temporanee. Tutte le tabelle temporanee sono state create con:

CREATE TEMPORARY TABLE... ON COMMIT DELETE ROWS;

La semantica delle tabelle temporanee si adatta molto bene al nostro schema di replica e ha semplificato gran parte del codice che dovevamo usare per MySQL, ma sembra che l'implementazione non sia corretta. Dal po 'di ricerca che ho fatto, non credo che le tabelle temporanee fossero davvero pensate per la funzione per cui le stavamo usando.

Non sono un esperto interno (nemmeno vicino) su questo argomento, ne sono solo un utente, quindi la mia spiegazione potrebbe non essere accurata al 100%, ma penso che sia abbastanza vicina.


3
La tua comprensione è un po 'datata, se guardi la documentazione ufficiale , scoprirai che "... per le relazioni temporanee, il nome del file è nel formato tBBB_FFF, dove BBB è l'ID backend del backend che ha creato il file e FFF è il numero del nome file. ... "
Milen A. Radev il

Wow, questo è un sottosistema di I / O del disco ben funzionante. Che cosa dice Strace su ciò che i lavoratori stanno effettivamente facendo?
Womble

@ MilenA.Radev, quindi sembra che potrei fare qualcosa di strano / eccessivo con le tabelle temporanee. Questo è interessante. Ho un sacco di trigger in atto che fanno uso di tabelle temporanee. Guarderò più da vicino a questi.
Wolfolf,

@womble, ho aggiornato la domanda con l'output di strace.
Wolfolf,

Stai effettivamente riscontrando un problema di prestazioni?
voretaq7,

Risposte:


1

La tua configurazione PostgreSQL è lontana. Questo era sospetto dal tuo post iniziale,

 Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
 Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
 Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

Su 32 GB sul server, ~ 25 GB sono gratuiti escludendo ~ 575 MB di buffer.

Dal tuo file postgresql.conf,

 shared_buffers = 32MB                   # min 128kB                               
 #temp_buffers = 8MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 #work_mem = 1MB                         # min 64kB
 #maintenance_work_mem = 16MB            # min 1MB
 #max_stack_depth = 2MB   

Suppongo che questo sia un database dedicato. In tal caso, modificalo nei seguenti parametri e ricarica / riavvia,

 shared_buffers = 16GB                   # min 128kB                               
 temp_buffers = 128MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 work_mem = 8MB                         # min 64kB
 maintenance_work_mem = 64MB            # min 1MB
 max_stack_depth = 4MB   

Fammi sapere come questo cambia le tue prestazioni e puoi regolarle ulteriormente se necessario.

Per quanto riguarda le tabelle non blog, se le tue tabelle temporanee contengono dati temporanei che sono effimeri e, come hai già detto, vengono creati in sessione, è meglio usare tabelle non blog.

Puoi troncare le tue tabelle dopo la sessione se ciò è accettabile.

Maggiori informazioni qui - http://michael.otacoo.com/postgresql-2/unlogged-table-performance-in-postgresql-9-1/

Non sono sicuro del motivo per cui sono necessarie tabelle temporanee per la replica. Non puoi usare la replica di streaming PostgreSQL?


0

L'uso di tabelle temporanee e la presenza di connessioni di lunga data (probabilmente è coinvolto il pool di connessioni) può essere un onere se il server non è preparato ad esso. Un parametro PostgreSQL con cui puoi provare a giocare è temp_buffersche controlla la RAM allocata alle tabelle temporanee. Questi buffer temporanei vengono allocati per connessione e il valore predefinito (8 MB) è probabilmente troppo basso per il tuo sito.

Forse devi anche modificare un po 'il comportamento della tua applicazione client, a seconda di come usi le tue tabelle temporanee. C'è una domanda simile con una bella risposta su Stack Overflow .


Dovrò chiedere al mio esperto interno se abbiamo provato a modificare il valore di temp_buffers o meno (abbiamo provato molte cose diverse). La domanda a cui fai riferimento non si applica in quanto non stiamo utilizzando le tabelle temporanee in quel modo. Ho aggiornato la domanda con qualche dettaglio in più.
Wolfolf

Grazie per l'aggiornamento alla domanda e per il file postgresql.conf, questo è ciò che dobbiamo cercare di migliorare in questa situazione. Sono d'accordo con la risposta di @Chida che sono in linea con ciò che ho suggerito temp_buffers. Puoi dirci qual è la dimensione del DB che stai tentando di replicare? Quante tabelle, dimensione media per tabella e dimensione totale del DB?
Tonin,

0

Potresti pubblicare il tuo file postgresql.conf? Il tuo postgresql sembra essere notevolmente ottimizzato.

Potresti anche pubblicare:

  • Se usi tabelle non blog per le tue tabelle temporanee?

  • Quanti dischi e in quale configurazione RAID?


Ho messo il file postgresql.conf qui . Io credo che non si può creare una tabella che sia temporanea e unlogged. Ci sono 6 dischi da 1 TB in un RAID 1 + 0 (3 TB di memoria totale)
wolfcastle
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.