Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Ti suggerisco di leggere la trascrizione del rapporto di inizio 2016 di Andrey Salnikov “Errori tipici nelle applicazioni che portano a gonfiare in postgresql”

In questo rapporto analizzerò i principali errori nelle applicazioni che si presentano nella fase di progettazione e scrittura del codice applicativo. E prenderò solo quegli errori che portano a gonfiare Postgresql. Di norma, questo è l'inizio della fine delle prestazioni del sistema nel suo insieme, sebbene inizialmente non fossero visibili prerequisiti per ciò.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Sono felice di dare il benvenuto a tutti! Questa relazione non è così tecnica come quella precedente del mio collega. Questo rapporto è rivolto principalmente agli sviluppatori di sistemi backend perché abbiamo un numero abbastanza elevato di clienti. E commettono tutti gli stessi errori. Te ne parlerò. Spiegherò a quali cose fatali e brutte portano questi errori.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Perché si commettono errori? Vengono eseguiti per due motivi: in modo casuale, forse funzionerà e per l'ignoranza di alcuni meccanismi che si verificano a livello tra il database e l'applicazione, nonché nel database stesso.

Ti farò tre esempi con immagini terribili di quanto siano andate male le cose. Ti parlerò brevemente del meccanismo che avviene lì. E come affrontarli, quando si sono verificati e quali metodi preventivi utilizzare per evitare errori. Ti parlerò degli strumenti ausiliari e fornirò collegamenti utili.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Ho utilizzato un database di prova in cui avevo due tabelle. Una piastra con i conti dei clienti, l'altra con le transazioni su questi conti. E con una certa frequenza aggiorniamo i saldi di questi conti.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Dati iniziali della targa: è piuttosto piccola, 2 MB. Anche il tempo di risposta del database e in particolare del segnale è molto buono. E un carico abbastanza buono: 2 operazioni al secondo secondo la targa.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

E attraverso questo report ti mostrerò dei grafici in modo che tu possa capire chiaramente cosa sta succedendo. Ci saranno sempre 2 diapositive con grafici. La prima diapositiva è ciò che accade in generale sul server.

E in questa situazione vediamo che abbiamo davvero un piccolo segno. L'indice è piccolo a 2 MB. Questo è il primo grafico a sinistra.

Anche il tempo medio di risposta sul server è stabile e breve. Questo è il grafico in alto a destra.

Il grafico in basso a sinistra mostra le transazioni più lunghe. Vediamo che le transazioni vengono completate rapidamente. E qui l’autovuoto non funziona ancora, perché era un test di avvio. Continuerà a funzionare e ci sarà utile.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

La seconda diapositiva sarà sempre dedicata alla piastra in prova. In questa situazione, aggiorniamo costantemente i saldi dei conti del cliente. E vediamo che il tempo medio di risposta per un'operazione di aggiornamento è abbastanza buono, inferiore a un millisecondo. Vediamo che anche le risorse del processore (questo è il grafico in alto a destra) vengono consumate in modo uniforme e piuttosto ridotto.

Il grafico in basso a destra mostra la quantità di memoria operativa e del disco che utilizziamo per cercare la riga desiderata prima di aggiornarla. E il numero di operazioni secondo il segno è 2 al secondo, come ho detto all'inizio.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

E ora abbiamo una tragedia. Per qualche motivo c'è una transazione dimenticata da tempo. I motivi sono solitamente tutti banali:

  • Uno dei più comuni è che abbiamo iniziato ad accedere a un servizio esterno nel codice dell'applicazione. E questo servizio non ci risponde. Cioè, abbiamo aperto una transazione, apportato una modifica al database e siamo passati dall'applicazione alla lettura della posta o ad un altro servizio all'interno della nostra infrastruttura, e per qualche motivo non ci risponde. E la nostra sessione è bloccata in uno stato in cui non si sa quando verrà risolta.
  • La seconda situazione è quando si è verificata un'eccezione nel nostro codice per qualche motivo. E nell'eccezione non abbiamo elaborato la chiusura della transazione. E alla fine ci siamo ritrovati con una sessione sospesa con una transazione aperta.
  • E anche l'ultimo è un caso abbastanza comune. Questo è un codice di bassa qualità. Alcuni framework aprono una transazione. Si blocca e potresti non sapere nell'applicazione che è sospeso.

Dove portano queste cose?

Al punto che le nostre tabelle e i nostri indici cominciano a gonfiarsi a dismisura. Questo è esattamente lo stesso effetto gonfio. Per il database, ciò significherà che il tempo di risposta del database aumenterà notevolmente e il carico sul server del database aumenterà. Di conseguenza, la nostra applicazione ne risentirà. Perché se spendi 10 millisecondi nel tuo codice su una richiesta al database, 10 millisecondi nella tua logica, la tua funzione impiegherà 20 millisecondi per essere completata. E ora la tua situazione sarà molto triste.

E vediamo cosa succede. Il grafico in basso a sinistra mostra che abbiamo una transazione lunga e lunga. E se guardiamo il grafico in alto a sinistra, vediamo che la dimensione della nostra tabella è improvvisamente balzata da due megabyte a 300 megabyte. Allo stesso tempo, la quantità di dati nella tabella non è cambiata, ad es. lì c'è una quantità abbastanza grande di spazzatura.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Anche la situazione generale relativa al tempo medio di risposta del server è cambiata di diversi ordini di grandezza. Cioè, tutte le richieste sul server hanno iniziato a diminuire completamente. E allo stesso tempo, sono stati lanciati processi interni di Postgres sotto forma di autovacuum, che stanno cercando di fare qualcosa e consumando risorse.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Cosa sta succedendo al nostro segno? Lo stesso. Il nostro tempo medio di risposta in base al segno è aumentato di diversi ordini di grandezza. Nello specifico in termini di risorse consumate, vediamo che il carico sul processore è aumentato notevolmente. Questo è il grafico in alto a destra. Ed è aumentato perché il processore deve smistare un mucchio di righe inutili alla ricerca di quella necessaria. Questo è il grafico in basso a destra. Di conseguenza, il nostro numero di chiamate al secondo ha iniziato a diminuire in modo molto significativo, perché il database non ha avuto il tempo di elaborare lo stesso numero di richieste.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Dobbiamo tornare alla vita. Andiamo online e scopriamo che le transazioni lunghe portano a problemi. Troviamo e uccidiamo questa transazione. E tutto sta diventando normale per noi. Tutto funziona come dovrebbe.

Ci siamo calmati, ma dopo un po’ cominciamo a notare che l’applicazione non funziona come prima dell’emergenza. Le richieste vengono ancora elaborate più lentamente e significativamente più lentamente. Da una volta e mezza a due volte più lento, in particolare nel mio esempio. Anche il carico sul server è maggiore rispetto a prima dell'incidente.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

E la domanda: "Cosa sta succedendo alla base in questo momento?" E con la base si verifica la seguente situazione. Sul grafico delle transazioni puoi vedere che si è fermato e in realtà non ci sono transazioni a lungo termine. Ma durante l'incidente le dimensioni del cartello aumentarono fatalmente. E da allora non sono diminuiti. Il tempo medio sulla base si è stabilizzato. E le risposte sembrano arrivare adeguatamente e a una velocità per noi accettabile. L'autovuoto è diventato più attivo e ha iniziato a fare qualcosa con il segno, perché ha bisogno di vagliare più dati.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Nello specifico, secondo la targa di prova con i conti, dove cambiamo i saldi: i tempi di risposta ad una richiesta sembrano essere tornati alla normalità. Ma in realtà è una volta e mezza più alto.

E dal carico sul processore, vediamo che il carico sul processore non è tornato al valore richiesto prima dell'arresto anomalo. E le ragioni risiedono proprio nel grafico in basso a destra. Si può vedere che lì viene cercata una certa quantità di memoria. Cioè, per trovare la riga richiesta, sprechiamo le risorse del server del database mentre selezioniamo i dati inutili. Il numero di transazioni al secondo si è stabilizzato.

Nel complesso bene, ma la situazione è peggiore di prima. Cancella il degrado del database come conseguenza della nostra applicazione che funziona con questo database.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

E per capire cosa sta succedendo, se non eri presente al rapporto precedente, ora facciamo un po’ di teoria. Teoria del processo interno. Perché un aspirapolvere per auto e cosa fa?

Letteralmente brevemente per capire. Ad un certo punto abbiamo un tavolo. Abbiamo righe nella tabella. Queste linee possono essere attive, vive e ciò di cui abbiamo bisogno ora. Nella foto sono contrassegnati in verde. E ci sono scadenze che sono già state elaborate, sono state aggiornate e su di esse sono apparse nuove voci. E vengono contrassegnati come non interessanti per il database. Ma sono nella tabella a causa di una funzionalità di Postgres.

Perché hai bisogno di un aspirapolvere per auto? Ad un certo punto arriva l’autovacuum, accede al database e gli chiede: “Per favore dammi l’id della transazione più vecchia attualmente aperta nel database”. Il database restituisce questo ID. E l'autovuoto, basandosi su di esso, ordina le righe della tabella. E se vede che alcune righe sono state modificate da transazioni molto più vecchie, allora ha il diritto di contrassegnarle come righe che possiamo riutilizzare in futuro scrivendovi nuovi dati. Questo è un processo in background.

Al momento continuiamo a lavorare con il database e ad apportare alcune modifiche alla tabella. E su queste righe, che possiamo riutilizzare, scriviamo nuovi dati. E così otteniamo un ciclo, ad es. ogni volta che compaiono alcune vecchie righe morte, invece di esse scriviamo nuove righe di cui abbiamo bisogno. E questo è uno stato normale per il funzionamento di PostgreSQL.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Cosa è successo durante l'incidente? Come è avvenuto questo processo lì?

Avevamo un segnale in alcune condizioni, alcuni vivi, altri morti. L'aspirapolvere per auto è arrivato. Ha chiesto al database qual è la nostra transazione più vecchia e qual è il suo ID. Ho ricevuto questo ID, che potrebbe risalire a molte ore fa, forse dieci minuti fa. Dipende da quanto è pesante il carico che hai sul tuo database. E andò alla ricerca di linee che potesse contrassegnare come riutilizzate. E non ho trovato tali righe nella nostra tabella.

Ma in questo momento continuiamo a lavorare con il tavolo. Facciamo qualcosa, lo aggiorniamo, cambiamo i dati. Cosa dovrebbe fare il database in questo momento? Non ha altra scelta che aggiungere nuove righe alla fine della tabella esistente. E così la dimensione del nostro tavolo comincia a gonfiarsi.

In realtà, abbiamo bisogno che le linee verdi funzionino. Ma durante un problema del genere, si scopre che la percentuale di linee verdi è estremamente bassa sull'intera tabella.

E quando eseguiamo una query, il database deve passare attraverso tutte le linee: sia rossa che verde, per trovare la linea desiderata. E l’effetto di gonfiare una tabella con dati inutili si chiama “bloat”, e consuma anche il nostro spazio su disco. Ricordi, erano 2 MB, sono diventati 300 MB? Ora cambia megabyte in gigabyte e perderai rapidamente tutte le risorse del tuo disco.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Quali conseguenze potrebbero esserci per noi?

  • Nel mio esempio, la tabella e l'indice sono cresciuti di 150 volte. Alcuni dei nostri clienti hanno avuto casi più fatali quando hanno semplicemente iniziato a rimanere a corto di spazio su disco.
  • La dimensione dei tavoli stessi non diminuirà mai. L'autovacuum in alcuni casi può tagliare la coda del tavolo se ci sono solo linee morte. Ma poiché la rotazione è costante, una linea verde potrebbe bloccarsi alla fine e non essere aggiornata, mentre tutte le altre verranno scritte da qualche parte all'inizio della tavola. Ma questo è un evento così improbabile che il tuo tavolo stesso si ridurrà di dimensioni, quindi non dovresti sperarlo.
  • Il database deve ordinare un sacco di righe inutili. E sprechiamo risorse del disco, sprechiamo risorse del processore ed elettricità.
  • E questo influisce direttamente sulla nostra applicazione, perché se all'inizio dedicavamo 10 millisecondi alla richiesta, 10 millisecondi al nostro codice, poi durante il crash abbiamo iniziato a dedicare un secondo alla richiesta e 10 millisecondi al codice, cioè un ordine di l'entità delle prestazioni dell'applicazione è diminuita. E quando l'incidente si è risolto, abbiamo iniziato a dedicare 20 millisecondi a una richiesta, 10 millisecondi a un codice. Ciò significa che la produttività è comunque diminuita di una volta e mezza. E tutto questo a causa di una transazione che si è bloccata, forse per colpa nostra.
  • E la domanda: “Come possiamo riavere tutto?” affinché tutto vada bene e le richieste arrivino con la stessa rapidità di prima dell'incidente.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

A questo scopo viene svolto un certo ciclo di lavoro.

Per prima cosa dobbiamo trovare le tabelle problematiche che sono gonfie. Capiamo che in alcune tabelle la registrazione è più attiva, in altre meno attiva. E per questo usiamo l'estensione pgstattuple. Installando questa estensione, puoi scrivere query che ti aiuteranno a trovare tabelle piuttosto gonfie.

Una volta trovate queste tabelle, è necessario comprimerle. Esistono già strumenti per questo. Nella nostra azienda utilizziamo tre strumenti. Il primo è il VACUUM FULL integrato. È crudele, duro e spietato, ma a volte è molto utile. Pg_repack и pgcompacttable - Queste sono utilità di terze parti per la compressione delle tabelle. E trattano il database con più attenzione.

Vengono utilizzati a seconda di ciò che è più conveniente per te. Ma di questo ti parlerò proprio alla fine. La cosa principale è che ci sono tre strumenti. Ce ne sono molti tra cui scegliere.

Dopo aver corretto tutto e assicurato che tutto vada bene, dobbiamo sapere come prevenire questa situazione in futuro:

  • Può essere prevenuto abbastanza facilmente. È necessario monitorare la durata delle sessioni sul server Master. Sessioni particolarmente pericolose nello stato di inattività della transazione. Questi sono quelli che hanno appena aperto una transazione, hanno fatto qualcosa e se ne sono andati, o semplicemente sono rimasti bloccati, perdendosi nel codice.
  • E per te, come sviluppatori, è importante testare il tuo codice quando si verificano queste situazioni. Non è difficile da fare. Sarà un controllo utile. Eviterai un gran numero di problemi “infantili” associati alle transazioni lunghe.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

In questi grafici, volevo mostrarti come sono cambiati il ​​segno e il comportamento del database dopo aver superato il segno con VACUUM FULL in questo caso. Questa non è produzione per me.

La dimensione della tabella è tornata immediatamente al normale stato operativo di un paio di megabyte. Ciò non ha influito notevolmente sul tempo di risposta medio del server.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Ma nello specifico per il nostro segnale di prova, in cui abbiamo aggiornato i saldi dei conti, vediamo che il tempo medio di risposta per una richiesta di aggiornamento dei dati nel segnale è stato ridotto ai livelli pre-emergenza. Anche le risorse consumate dal processore per completare questa richiesta sono scese ai livelli pre-crash. E il grafico in basso a destra mostra che ora troviamo esattamente la linea di cui abbiamo bisogno subito, senza passare attraverso le pile di linee morte che erano lì prima che la tabella fosse compressa. E il tempo medio di richiesta è rimasto approssimativamente allo stesso livello. Ma qui ho piuttosto un errore nel mio hardware.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Qui finisce la prima storia. È il più comune. E succede a tutti, indipendentemente dall’esperienza del cliente e dalla qualificazione dei programmatori. Prima o poi questo accade.

La seconda storia, in cui distribuiamo il carico e ottimizziamo le risorse del server

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

  • Siamo già cresciuti e siamo diventati ragazzi seri. E capiamo che abbiamo una replica e sarebbe bene per noi bilanciare il carico: scrivere al Master e leggere dalla replica. E di solito questa situazione si verifica quando vogliamo preparare dei report o ETL. E gli affari ne sono molto contenti. Vuole davvero una varietà di rapporti con molte analisi complesse.
  • I report richiedono molte ore, perché analisi complesse non possono essere calcolate in millisecondi. Noi, come ragazzi coraggiosi, scriviamo codice. Nell'applicazione di inserimento effettuiamo la registrazione sul Master, ed eseguiamo i report sulla replica.
  • Distribuire il carico.
  • Tutto funziona perfettamente. Erano grandi.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

E come si presenta questa situazione? Nello specifico su questi grafici ho aggiunto anche la durata delle transazioni dalla replica alla durata della transazione. Tutti gli altri grafici si riferiscono solo al server Master.

A questo punto, la mia bacheca era cresciuta. Ce ne sono altri. Vediamo che il tempo medio di risposta del server è stabile. Vediamo che sulla replica abbiamo una transazione di lunga durata che dura 2 ore. Vediamo il funzionamento silenzioso dell'autovacuum, che elabora le linee morte. E per noi va tutto bene.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Nello specifico, secondo la targa testata, continuiamo ad aggiornare i saldi dei conti lì. E abbiamo anche tempi di risposta stabili per le richieste, consumo stabile di risorse. Per noi va tutto bene.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Tutto va bene fino al momento in cui questi rapporti iniziano a rispondere a causa di un conflitto con la replica. E rispondono a intervalli regolari.

Andiamo online e iniziamo a leggere perché questo sta accadendo. E troviamo una soluzione.

La prima soluzione è aumentare la latenza di replica. Sappiamo che il nostro rapporto dura 3 ore. Impostiamo il ritardo di replica su 3 ore. Stiamo lanciando tutto, ma continuiamo ancora ad avere problemi con i rapporti che a volte vengono cancellati.

Vogliamo che tutto sia perfetto. Saliamo ulteriormente. E abbiamo trovato un'impostazione interessante su Internet: hot_standby_feedback. Accendiamolo. Hot_standby_feedback ci permette di trattenere l'autovacuum sul Master. Pertanto, eliminiamo completamente i conflitti di replica. E tutto funziona bene per noi con i report.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

E cosa sta succedendo al server Master in questo momento? E siamo nei guai con il server principale. Ora vediamo i grafici quando ho abilitato entrambe queste impostazioni. E vediamo che la sessione sulla nostra replica in qualche modo ha iniziato a influenzare la situazione sul server Master. Ha un effetto perché ha messo in pausa l'autovuoto, che cancella le linee morte. Le dimensioni del nostro tavolo sono nuovamente salite alle stelle. Anche il tempo medio di esecuzione delle query sull'intero database è salito alle stelle. Gli autoaspiratori si sono ristretti un po'.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Nello specifico, dalla nostra targa, vediamo che anche l'aggiornamento dei dati a riguardo è balzato in cielo. Allo stesso modo, il consumo della CPU è aumentato notevolmente. Stiamo ancora attraversando un gran numero di linee morte e inutili. E i tempi di risposta per questo segnale e il numero di transazioni sono diminuiti.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Come sarà se non sapessimo di cosa stavo parlando prima?

  • Iniziamo a cercare problemi. Se abbiamo riscontrato problemi nella prima parte, sappiamo che ciò potrebbe essere dovuto a una transazione lunga e andiamo al Master. Abbiamo un problema sul Master. Lo insacca. Si riscalda, il suo carico medio è di circa cento.
  • Le richieste sono lente, ma non vediamo transazioni di lunga durata. E non capiamo qual è il problema. Non capiamo dove guardare.
  • Controlliamo l'attrezzatura del server. Forse il nostro raid è fallito. Forse la nostra memory stick è bruciata. Sì, tutto può succedere. Ma no, i server sono nuovi, tutto funziona bene.
  • Tutti corrono: amministratori, sviluppatori e il direttore. Niente aiuta.
  • E ad un certo punto tutto comincia improvvisamente a correggersi.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

In questo momento, la richiesta sulla nostra replica è stata elaborata e lasciata. Abbiamo ricevuto la segnalazione. Gli affari sono ancora felici. Come puoi vedere, il nostro segno è cresciuto di nuovo e non si ridurrà. Sul grafico con le sessioni ho lasciato una parte di questa lunga transazione da una replica in modo che tu possa stimare quanto tempo ci vuole perché la situazione si stabilizzi.

La sessione è finita. E solo dopo un po' il server torna più o meno in ordine. E il tempo medio di risposta per le richieste sul server Master ritorna alla normalità. Perché, finalmente, l’autovuoto ha l’opportunità di ripulire e segnare queste linee morte. E cominciò a fare il suo lavoro. E quanto velocemente lo fa, così velocemente metteremo ordine.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Secondo il tablet testato, dove aggiorniamo i saldi dei conti, vediamo esattamente la stessa immagine. Anche il tempo medio di aggiornamento dell'account si sta gradualmente normalizzando. Anche le risorse consumate dal processore sono ridotte. E il numero di transazioni al secondo ritorna alla normalità. Ma ancora una volta siamo tornati alla normalità, non più come prima dell’incidente.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

In ogni caso, otteniamo un calo delle prestazioni, come nel primo caso, da una volta e mezza a due volte, e talvolta di più.

Sembra che abbiamo fatto tutto bene. Distribuire il carico. L'attrezzatura non è inattiva. Abbiamo diviso le richieste secondo le nostre menti, ma comunque tutto è andato male.

  • Non abilitare hot_standby_feedback? Sì, non è consigliabile accenderlo senza ragioni particolarmente forti. Perché questa svolta colpisce direttamente il server master e lì sospende il funzionamento dell'autovacuum. Abilitandolo su qualche replica e dimenticandolo, puoi uccidere il Master e avere grossi problemi con l'applicazione.
  • Aumentare max_standby_streaming_delay? Sì, per i report questo è vero. Se hai un report di tre ore e non vuoi che si blocchi a causa di conflitti di replica, aumenta semplicemente il ritardo. Un report a lungo termine non richiede mai dati arrivati ​​​​nel database in questo momento. Se lo hai per tre ore, lo stai eseguendo per un vecchio periodo di dati. E per te, che ci sia un ritardo di tre o sei ore non farà alcuna differenza, ma riceverai i rapporti in modo coerente e non avrai problemi con la loro caduta.
  • Naturalmente è necessario controllare le lunghe sessioni sulle repliche, soprattutto se si decide di abilitare hot_standby_feedback su una replica. Perché tutto può succedere. Abbiamo fornito questa replica allo sviluppatore in modo che potesse testare le query. Ha scritto una richiesta pazzesca. Lo lanciò e andò a bere il tè, e trovammo il Maestro affermato. O forse abbiamo inserito l'applicazione sbagliata. Le situazioni sono varie. Le sessioni sulle repliche devono essere monitorate con la stessa attenzione che sul Master.
  • E se hai query veloci e lunghe sulle repliche, in questo caso è meglio dividerle per distribuire il carico. Questo è un collegamento a streaming_delay. Per quelli veloci, disponi di una replica con un piccolo ritardo di replica. Per le richieste di reporting di lunga durata, disporre di una replica che può ritardare di 6 ore o di un giorno. Questa è una situazione del tutto normale.

Eliminiamo le conseguenze allo stesso modo:

  • Troviamo tavoli gonfi.
  • E lo comprimiamo con lo strumento più conveniente e adatto a noi.

La seconda storia finisce qui. Passiamo alla terza storia.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Anche abbastanza comune per noi in cui effettuiamo la migrazione.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

  • Qualsiasi prodotto software è in crescita. I requisiti per farlo stanno cambiando. In ogni caso, vogliamo svilupparci. E succede che dobbiamo aggiornare i dati nella tabella, ovvero eseguire un aggiornamento in termini di migrazione per la nuova funzionalità che stiamo introducendo come parte del nostro sviluppo.
  • Il vecchio formato dei dati non è soddisfacente. Diciamo che passiamo ora alla seconda tabella, dove ho transazioni su questi conti. E diciamo che erano in rubli, e abbiamo deciso di aumentare la precisione e di farlo in centesimi. E per questo occorre fare un aggiornamento: moltiplicare per cento il campo con l'importo della transazione.
  • Nel mondo di oggi utilizziamo strumenti automatizzati di controllo della versione del database. Diciamo Liquido base. Registriamo lì la nostra migrazione. Lo testiamo sulla nostra base di test. Va tutto bene. L'aggiornamento è in corso. Blocca il lavoro per un po', ma otteniamo dati aggiornati. E possiamo lanciare nuove funzionalità su questo. Tutto è stato testato e controllato. Tutto è stato confermato.
  • Abbiamo svolto il lavoro pianificato e effettuato la migrazione.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Ecco la migrazione con l'aggiornamento presentato di fronte a te. Poiché queste sono le transazioni del mio conto, la piastra era di 15 GB. E poiché aggiorniamo ogni riga, abbiamo raddoppiato la dimensione della tabella con l'aggiornamento, perché abbiamo riscritto ogni riga.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Durante la migrazione non abbiamo potuto fare nulla con questa piastra, perché tutte le richieste sono state messe in coda e hanno aspettato fino al completamento dell'aggiornamento. Ma qui voglio attirare la tua attenzione sui numeri che si trovano sull'asse verticale. Cioè, abbiamo un tempo medio di richiesta prima della migrazione di circa 5 millisecondi e con il carico del processore, il numero di operazioni di blocco per leggere la memoria del disco è inferiore a 7,5.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Abbiamo effettuato la migrazione e abbiamo riscontrato nuovamente problemi.

La migrazione è riuscita, ma:

  • Il completamento della vecchia funzionalità ora richiede più tempo.
  • Il tavolo si ingrandì nuovamente.
  • Il carico sul server è diventato nuovamente maggiore di prima.
  • E, naturalmente, stiamo ancora armeggiando con la funzionalità che ha funzionato bene, l'abbiamo leggermente migliorata.

E questo è ancora una volta eccessivo, che rovina ancora una volta le nostre vite.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Qui dimostro che la tabella, come nei due casi precedenti, non tornerà alle dimensioni precedenti. Il carico medio del server sembra essere adeguato.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

E se passiamo alla tabella dei conti, vedremo che il tempo medio di richiesta per questa tabella è raddoppiato. Il carico sul processore e il numero di righe risolte in memoria sono saliti sopra 7,5, ma erano inferiori. Ed è saltato 2 volte nel caso dei processori, 1,5 volte nel caso delle operazioni a blocchi, ad es. abbiamo riscontrato un degrado delle prestazioni del server. E di conseguenza: degrado delle prestazioni della nostra applicazione. Allo stesso tempo, il numero di chiamate è rimasto approssimativamente allo stesso livello.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

E la cosa principale qui è capire come eseguire correttamente tali migrazioni. E devono essere fatti. Eseguiamo queste migrazioni in modo abbastanza coerente.

  • Migrazioni così grandi non avvengono automaticamente. Devono essere sempre sotto controllo.
  • È necessaria la supervisione di una persona esperta. Se hai un DBA nel tuo team, lascia che lo faccia il DBA. E' il suo lavoro. In caso contrario, lascia che lo faccia la persona più esperta, che sa come lavorare con i database.
  • Un nuovo schema del database, anche se aggiorniamo una colonna, lo prepariamo sempre per fasi, cioè in anticipo prima che venga lanciata la nuova versione dell'applicazione:
  • Vengono aggiunti nuovi campi in cui registreremo i dati aggiornati.
  • Trasferiamo i dati dal vecchio campo al nuovo campo in piccole parti. Perché stiamo facendo questo? In primo luogo, controlliamo sempre il processo di questo processo. Sappiamo che abbiamo già trasferito così tanti lotti e ne restano così tanti.
  • E il secondo effetto positivo è che tra ciascuno di questi lotti chiudiamo la transazione, ne apriamo una nuova e questo consente all'autovuoto di funzionare secondo la piastra, segnando le scadenze per il riutilizzo.
  • Per le righe che appariranno mentre l'applicazione è in esecuzione (abbiamo ancora la vecchia applicazione in esecuzione), aggiungiamo un trigger che scrive nuovi valori in nuovi campi. Nel nostro caso si tratta della moltiplicazione per cento del vecchio valore.
  • Se siamo completamente testardi e desideriamo lo stesso campo, al termine di tutte le migrazioni e prima di implementare una nuova versione dell'applicazione, rinominiamo semplicemente i campi. A quelli vecchi viene dato un nome inventato e i nuovi campi vengono rinominati con quelli vecchi.
  • E solo dopo lanciamo una nuova versione dell'applicazione.

E allo stesso tempo non ci gonfieremo e non soffriremo in termini di prestazioni.

Qui finisce la terza storia.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

https://github.com/dataegret/pg-utils/blob/master/sql/table_bloat.sql

https://github.com/dataegret/pg-utils/blob/master/sql/table_bloat_approx.sql

E ora qualche dettaglio in più sugli strumenti di cui ho parlato nella primissima storia.

Prima di cercare bloat, devi installare l'estensione pgstattuple.

Per evitare che tu debba formulare domande, le abbiamo già scritte nel nostro lavoro. Puoi usarli. Qui ci sono due richieste.

  • Il primo richiede molto tempo per funzionare, ma ti mostrerà i valori esatti di gonfiamento dalla tabella.
  • Il secondo funziona più velocemente ed è molto efficace quando è necessario valutare rapidamente se c'è gonfiore o meno secondo la tabella. E dovresti anche capire che il gonfiore è sempre presente in una tabella Postgres. Questa è una caratteristica del suo modello MVCC.
  • E nella maggior parte dei casi un rigonfiamento del 20% è normale per le tabelle. Cioè, non dovresti preoccuparti e comprimere questa tabella.

Abbiamo capito come identificare le tabelle piene di dati inutili.

Ora su come correggere il gonfiore:

  • Se abbiamo un tablet piccolo e buoni dischi, cioè su un tablet fino a un gigabyte, è del tutto possibile utilizzare VACUUM FULL. Prenderà da te un lucchetto esclusivo sul tavolo per alcuni secondi e va bene, ma farà tutto in modo rapido e duro. Cosa fa VACUUM FULL? Richiede un blocco esclusivo sulla tabella e riscrive le righe attive dalle vecchie tabelle nella nuova tabella. E alla fine li sostituisce. Elimina i vecchi file e sostituisce quelli vecchi con quelli nuovi. Ma per tutta la durata del suo lavoro, occupa un posto esclusivo sul tavolo. Ciò significa che non puoi fare nulla con questa tabella: né scriverci, né leggerla, né modificarla. E VACUUM FULL richiede spazio su disco aggiuntivo per scrivere i dati.
  • Strumento successivo pg_repack. Nel suo principio è molto simile a VACUUM FULL, perché riscrive anche i dati dai vecchi file a quelli nuovi e li sostituisce nella tabella. Ma allo stesso tempo, non prende un blocco esclusivo sul tavolo proprio all'inizio del suo lavoro, ma lo prende solo nel momento in cui ha già dati pronti per sostituire i file. I suoi requisiti di risorse disco sono simili a quelli di VACUUM FULL. È necessario spazio su disco aggiuntivo e questo a volte è fondamentale se si dispone di tabelle da terabyte. Ed è piuttosto affamato di processore perché funziona attivamente con l'I/O.
  • La terza utilità è pgcompacttable. È più attenta alle risorse perché funziona secondo principi leggermente diversi. L'idea principale di pgcompacttable è che sposta tutte le righe attive all'inizio della tabella utilizzando gli aggiornamenti nella tabella. E poi viene creato un vuoto su questa tabella, perché sappiamo che abbiamo righe attive all'inizio e righe morte alla fine. E il vuoto stesso taglia questa coda, ad es. non richiede molto spazio aggiuntivo su disco. E allo stesso tempo può ancora essere spremuto in termini di risorse.

Tutto con strumenti.

Errori tipici nelle applicazioni che portano a gonfiare PostgreSQL. Andrej Salnikov

Se trovi interessante l'argomento gonfio in termini di approfondimento, ecco alcuni link utili:

Ho cercato di più di mostrare una storia dell'orrore per gli sviluppatori, perché sono i nostri clienti diretti dei database e devono capire cosa e quali azioni portano. Spero di esserci riuscito. Grazie per l'attenzione!

domande

Grazie per la segnalazione! Hai parlato di come identificare i problemi. Come possono essere avvisati? Cioè, ho avuto una situazione in cui le richieste si bloccavano non solo perché accedevano ad alcuni servizi esterni. Queste erano solo alcune unioni selvagge. C'erano alcune piccole richieste innocue che sono rimaste in sospeso per un giorno e poi hanno iniziato a fare delle sciocchezze. Cioè, molto simile a quello che descrivi. Come tenere traccia di questo? Sedersi e osservare costantemente quale richiesta è bloccata? Come è possibile prevenirlo?

In questo caso si tratta di un compito degli amministratori della vostra azienda, non necessariamente del DBA.

Sono un amministratore.

PostgreSQL ha una vista chiamata pg_stat_activity che mostra le query pendenti. E puoi vedere per quanto tempo resta lì.

Devo entrare a controllare ogni 5 minuti?

Imposta cron e controlla. Se hai una richiesta a lungo termine, scrivi una lettera e il gioco è fatto. Cioè, non è necessario guardare con gli occhi, può essere automatizzato. Riceverai una lettera, reagirai ad essa. Oppure puoi scattare automaticamente.

Ci sono ragioni ovvie per cui ciò accade?

Ne ho elencati alcuni. Altri esempi più complessi. E la conversazione può durare a lungo.

Grazie per la segnalazione! Volevo fare chiarezza sull'utilità pg_repack. Se non fa un blocco esclusivo, allora...

Fa una serratura esclusiva.

... quindi potrei potenzialmente perdere dati. La mia domanda non dovrebbe registrare nulla durante questo periodo?

No, funziona senza problemi con la tabella, cioè pg_repack trasferisce prima tutte le linee attive esistenti. Naturalmente, lì avviene una sorta di ingresso nella tabella. Sta proprio buttando via questa coda di cavallo.

Cioè, alla fine lo fa davvero?

Alla fine, prende un blocco esclusivo per scambiare questi file.

Sarà più veloce di VACUUM FULL?

VACUUM FULL, appena avviato, ha subito preso una serratura esclusiva. E finché non farà tutto, non la lascerà andare. E pg_repack accetta un blocco esclusivo solo al momento della sostituzione del file. In questo momento non scriverai lì, ma i dati non andranno persi, andrà tutto bene.

Ciao! Hai parlato del funzionamento di un aspirapolvere per auto. C'era un grafico con celle di registrazione rosse, gialle e verdi. Cioè quelli gialli: li ha contrassegnati come cancellati. E di conseguenza, è possibile scrivere qualcosa di nuovo in essi?

SÌ. Postgres non elimina le righe. Ha una tale specificità. Se aggiornavamo una riga, contrassegnavamo quella vecchia come eliminata. Lì appare l'ID della transazione che ha modificato questa riga e scriviamo una nuova riga. E abbiamo sessioni che potrebbero potenzialmente leggerli. Ad un certo punto diventano piuttosto vecchi. E l’essenza del funzionamento dell’autovuoto è che attraversa queste linee e le contrassegna come non necessarie. E puoi sovrascrivere i dati lì.

Capisco. Ma non è questo il punto della questione. Non ho finito. Supponiamo di avere una tabella. Ha campi di dimensione variabile. E se provo a inserire qualcosa di nuovo, potrebbe semplicemente non adattarsi alla vecchia cella.

No, comunque lì viene aggiornata tutta la linea. Postgres ha due modelli di archiviazione dei dati. Seleziona dal tipo di dati. Ci sono dati memorizzati direttamente nella tabella e ci sono anche dati tos. Si tratta di grandi quantità di dati: testo, json. Sono conservati in piastre separate. E secondo queste compresse, si verifica la stessa storia con Gonfiore, ad es. tutto è uguale. Sono semplicemente elencati separatamente.

Grazie per la segnalazione! È accettabile utilizzare query di timeout delle istruzioni per limitare la durata?

Molto accettabile. Lo usiamo ovunque. E poiché non disponiamo di servizi propri, forniamo supporto remoto, abbiamo una vasta gamma di clienti. E tutti ne sono completamente soddisfatti. Cioè, abbiamo lavori cron che controllano. La durata delle sedute viene semplicemente concordata con il cliente, prima della quale non ci accordiamo. Potrebbe essere un minuto, potrebbero essere 10 minuti. Dipende dal carico sulla base e dal suo scopo. Ma usiamo tutti pg_stat_activity.

Grazie per la segnalazione! Sto cercando di applicare il tuo rapporto alle mie candidature. E sembra che iniziamo una transazione ovunque e la completiamo chiaramente ovunque. Se c'è qualche eccezione, il rollback avviene comunque. E poi ho iniziato a pensare. Dopotutto, la transazione potrebbe non iniziare in modo esplicito. Questo è probabilmente un suggerimento per la ragazza. Se aggiorno semplicemente un record, la transazione inizierà in PostgreSQL e verrà completata solo quando la connessione verrà disconnessa?

Se ora parli del livello dell'applicazione, dipende dal driver che stai utilizzando, dall'ORM che viene utilizzato. Ci sono molte impostazioni lì. Se hai attivato il commit automatico, la transazione inizia da lì e si chiude immediatamente.

Cioè si chiude subito dopo l'aggiornamento?

Dipende dalle impostazioni. Ho nominato un'impostazione. Questo è l'impegno automatico. È abbastanza comune. Se è abilitato, la transazione è stata aperta e chiusa. A meno che tu non abbia detto esplicitamente "avvia transazione" e "termina transazione", ma hai semplicemente lanciato una richiesta nella sessione.

Ciao! Grazie per la segnalazione! Immaginiamo di avere un database che si gonfia sempre più e che lo spazio sul server si esaurisce. Esistono strumenti per risolvere questa situazione?

Lo spazio sul server deve essere monitorato correttamente.

Ad esempio, il DBA è andato a prendere il tè, è stato in un resort, ecc.

Quando viene creato un file system, viene creato almeno un qualche tipo di spazio di backup in cui i dati non vengono scritti.

E se fosse completamente sotto lo zero?

Lì si chiama spazio riservato, cioè può essere liberato e, a seconda di quanto è stato creato, ottieni spazio libero. Per impostazione predefinita non so quanti ce ne siano. E in un altro caso, consegnare i dischi in modo da avere spazio per eseguire un'operazione ricostruttiva. Puoi eliminare alcune tabelle di cui sicuramente non avrai bisogno.

Ci sono altri strumenti?

È sempre fatto a mano. E a livello locale diventa chiaro cosa è meglio fare lì, perché alcuni dati sono critici e altri non sono critici. E per ciascun database e l'applicazione che lo supporta, dipende dall'azienda. Si decide sempre a livello locale.

Grazie per la segnalazione! Ho due domande. Innanzitutto, hai mostrato delle diapositive che mostravano che quando le transazioni sono bloccate, crescono sia la dimensione dello spazio tabella che quella dell'indice. E più avanti nel rapporto c'erano un sacco di utilità che impacchettano il tablet. E l'indice?

Anche loro li imballano.

Ma il vuoto non incide sull'indice?

Alcuni funzionano con un indice. Ad esempio, pg_rapack, pgcompacttable. Il vuoto ricrea gli indici e li incide. Con VACUUM FULL l'idea è di sovrascrivere tutto, cioè funziona con tutti.

E la seconda domanda. Non capisco perché i report sulle repliche dipendano così tanto dalla replica stessa. Mi è sembrato che i rapporti vengano letti e la replica venga scritta.

Che cosa causa un conflitto di replica? Abbiamo un Master sul quale si svolgono i processi. Abbiamo l'aspirapolvere in macchina in funzione. Cosa fa realmente un autoaspirapolvere? Sta ritagliando alcune vecchie battute. Se in questo momento abbiamo una richiesta sulla replica che legge queste vecchie righe, e sul Master si è verificata una situazione in cui l'autovacuum ha contrassegnato queste righe come possibili per la sovrascrittura, allora le abbiamo sovrascritte. E abbiamo ricevuto un pacchetto di dati, quando dobbiamo riscrivere quelle righe di cui la richiesta ha bisogno sulla replica, il processo di replica attenderà il timeout configurato. E poi PostgreSQL deciderà cosa è più importante per lui. E la replica è più importante per lui della richiesta, e fotograferà la richiesta per apportare queste modifiche alla replica.

Andrey, ho una domanda. Questi meravigliosi grafici che hai mostrato durante la presentazione, sono il risultato del lavoro di qualche tua utilità? Come sono stati realizzati i grafici?

Questo è un servizio Okmetro.

È un prodotto commerciale?

SÌ. Questo è un prodotto commerciale.

Fonte: habr.com

Aggiungi un commento