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

Aggiornamento a PostgreSQL 11 con replica logica

È ora.

Circa un anno fa abbiamo pubblicato PostgreSQL 10 con supporto per la replica logica nativa. Uno degli usi della replica logica è consentire l'aggiornamento con tempi di inattività ridotti o nulli tra le versioni principali di PostgreSQL. Fino ad ora, PostgreSQL 10 era l'unica versione di PostgreSQL con replica logica nativa, quindi non c'erano molte opportunità per l'aggiornamento in questo modo. (La replica logica può essere utilizzata anche per spostare i dati tra istanze su diversi sistemi operativi o architetture CPU o con diverse impostazioni di configurazione di basso livello come la dimensione del blocco o la localizzazione, se si desidera eseguire il sidegrading.) Ora che PostgreSQL 11 è vicino, ci sarà ulteriori motivi per utilizzare questa funzionalità.

Per prima cosa confrontiamo i tre modi principali per aggiornare un'installazione di PostgreSQL:

  • pg_dump e ripristina
  • pg_upgrade
  • replica logica

Possiamo confrontare questi metodi in termini di robustezza, velocità, tempi di inattività richiesti e restrizioni (e altro, ma dobbiamo fermarci da qualche parte per questo articolo).

pg_dump and restore è probabilmente il metodo più affidabile, poiché è il più testato ed è in uso da decenni. Ha anche pochissime restrizioni in termini di ciò che può gestire. È possibile costruire database che non possono essere scaricati e ripristinati, coinvolgendo principalmente relazioni di dipendenza da oggetti particolari, ma sono rari e di solito comportano pratiche scoraggiate.

Il problema con il metodo di dump e ripristino è ovviamente che richiede effettivamente tempi di inattività per tutto il tempo in cui vengono eseguite le operazioni di dump e ripristino. Mentre il database di origine è ancora leggibile e scrivibile durante l'esecuzione del processo, tutti gli aggiornamenti al database di origine dopo l'avvio del dump andranno persi.

pg_upgrade migliora il processo pg_dump spostando direttamente i file di dati senza doverli scaricare in una forma testuale logica. Si noti che pg_upgrade utilizza ancora pg_dump internamente per copiare lo schema, ma non i dati. Quando pg_upgrade era nuovo, la sua robustezza veniva messa in dubbio e aggiornava alcuni database in modo errato. Ma pg_upgrade è ora abbastanza maturo e ben testato, quindi non c'è più bisogno di esitare a usarlo per questo motivo. Durante l'esecuzione di pg_upgrade, il sistema del database è inattivo. Ma si può scegliere per quanto tempo viene eseguito pg_upgrade. Nella modalità di copia predefinita, il tempo di esecuzione totale è composto dal tempo per eseguire il dump e ripristinare lo schema (che di solito è molto veloce, a meno che non si disponga di migliaia di tabelle o altri oggetti) più il tempo per copiare i file di dati, che dipende da quanto è grande il database (e il sistema di I/O, il file system, ecc.).

Nella modalità di collegamento opzionale, i file di dati sono invece collegati fisicamente alla nuova directory di dati, in modo che il tempo sia semplicemente il momento di eseguire una breve operazione del kernel per file invece di copiare ogni byte. Lo svantaggio è che se qualcosa va storto con l'aggiornamento o è necessario ricorrere alla vecchia installazione, questa operazione avrà distrutto il vecchio database. (Sto lavorando a una soluzione migliore per PostgreSQL 12 utilizzando reflink o operazioni di clonazione di file su file system supportati.)

La replica logica è la più recente del gruppo qui, quindi probabilmente ci vorrà del tempo per risolvere i nodi. Se non hai tempo per esplorare e indagare, questa potrebbe non essere la strada da percorrere in questo momento. (Naturalmente, le persone utilizzano da molti anni altre soluzioni di replica logica non core come Slony, Londiste e pglogical per l'aggiornamento di PostgreSQL, quindi c'è molta esperienza con i principi, se non con i dettagli.)

Il vantaggio dell'utilizzo della replica logica per l'aggiornamento è che l'applicazione può continuare a essere eseguita sull'istanza precedente durante la sincronizzazione dei dati. È necessaria solo una piccola interruzione mentre le connessioni client vengono commutate. Quindi, mentre un aggiornamento che utilizza la replica logica è probabilmente più lento dall'inizio alla fine rispetto all'utilizzo di pg_upgrade in modalità copia (e decisamente più lento rispetto all'utilizzo della modalità hardlink), non importa molto poiché il tempo di inattività effettivo può essere molto più breve.

Si noti che la replica logica attualmente non replica le modifiche allo schema. In questa procedura di aggiornamento proposta, lo schema viene ancora copiato tramite pg_dump, ma le successive modifiche allo schema non vengono trasferite. L'aggiornamento con la replica logica ha anche alcune altre restrizioni. Alcune operazioni non vengono acquisite dalla replica logica:oggetti di grandi dimensioni, TRUNCATE, modifiche di sequenza. Discuteremo soluzioni alternative per questi problemi in seguito.

Se hai degli standby fisici (e in caso contrario, perché no?), Ci sono anche alcune differenze da considerare tra i metodi. Con entrambi i metodi, devi creare nuovi standby fisici per l'istanza aggiornata. Con il dump e il ripristino, nonché con la replica logica, possono essere implementati prima dell'inizio dell'aggiornamento in modo che lo standby sia per lo più pronto una volta completata la sincronizzazione iniziale del ripristino o della replica logica, soggetta a ritardo di replica.

Con pg_upgrade, i nuovi standby devono essere creati al termine dell'aggiornamento del primario. (La documentazione di pg_upgrade lo descrive in modo più dettagliato.) Se ti affidi agli standby fisici per l'alta disponibilità, gli standby dovrebbero essere attivi prima di passare alla nuova istanza, quindi l'impostazione degli standby potrebbe influenzare i tuoi calcoli di temporizzazione complessivi.

Ma torniamo alla replica logica. Ecco come è possibile eseguire l'aggiornamento con la replica logica:

0. La vecchia istanza deve essere preparata per la replica logica. Ciò richiede alcune impostazioni di configurazione come descritto in http://www.postgresql.org/docs/10/static/logical-replication-config.html (principalmente wal_level = logical . Se risulta necessario apportare tali modifiche, sarà necessario riavviare il server. Quindi controllalo con largo anticipo. Controlla anche che pg_hba.conf sulla vecchia istanza è impostato per accettare connessioni dalla nuova istanza. (La modifica richiede solo una ricarica.)

1. Installa la nuova versione di PostgreSQL. Hai bisogno almeno del pacchetto server e del pacchetto client che contiene pg_dump. Molti pacchetti ora consentono l'installazione di più versioni affiancate. Se stai eseguendo macchine virtuali o istanze cloud, vale la pena considerare l'installazione della nuova istanza su un nuovo host.

2. Configurare una nuova istanza, ovvero eseguire initdb. La nuova istanza può avere impostazioni diverse da quella precedente, ad esempio locale, dimensione del segmento WAL o checksum. (Perché non sfruttare questa opportunità per attivare i checksum dei dati?)

3. Prima di avviare la nuova istanza, potrebbe essere necessario modificare alcune impostazioni di configurazione. Se l'istanza viene eseguita sullo stesso host dell'istanza precedente, è necessario impostare un numero di porta diverso. Inoltre, trasferisci tutte le modifiche personalizzate che hai apportato in postgresql.conf sulla tua vecchia istanza, come le impostazioni di memoria, max_connections , ecc. Allo stesso modo, crea pg_hba.conf impostazioni appropriate al proprio ambiente. Di solito puoi iniziare copiando il pg_hba.conf file dalla vecchia istanza. Se desideri utilizzare SSL, configuralo ora.

4. Avvia la nuova istanza (vuota) e verifica che funzioni in modo soddisfacente. Se configuri la nuova istanza su un nuovo host, verifica a questo punto di poter effettuare una connessione al database (usando psql) dal nuovo host alla vecchia istanza del database. Ne avremo bisogno nei passaggi successivi.

5. Copiare le definizioni dello schema con pg_dumpall. (Oppure puoi farlo con pg_dump per ogni database separatamente, ma poi non dimenticare gli oggetti globali come i ruoli.)

pg_dumpall -s >schemadump.sql
psql -d postgres -f schemadump.sql

Eventuali modifiche allo schema successive a questo punto non verranno migrate. Dovresti gestirli tu stesso. In molti casi, puoi semplicemente applicare la modifica DDL su entrambi gli host, ma l'esecuzione di comandi che modificano la struttura della tabella durante un aggiornamento è probabilmente una sfida troppo lontana.

6. In ogni database nell'istanza di origine, crea una pubblicazione che acquisisca tutte le tabelle:

CREATE PUBLICATION p_upgrade FOR ALL TABLES;

La replica logica funziona separatamente in ogni database, quindi è necessario ripeterla in ogni database. D'altra parte, non è necessario aggiornare tutti i database contemporaneamente, quindi puoi farlo un database alla volta o addirittura non aggiornare alcuni database.

7. In ogni database nell'istanza di destinazione, creare una sottoscrizione che sottoscriva la pubblicazione appena creata. Assicurati di abbinare correttamente i database di origine e di destinazione.

CREATE SUBSCRIPTION s_upgrade CONNECTION 'host=oldhost port=oldport dbname=dbname ...' PUBLICATION p_upgrade;

Impostare i parametri di connessione appropriati.

8. Ora attendi fino a quando gli abbonamenti non hanno copiato i dati iniziali e hanno raggiunto completamente l'editore. Puoi controllare lo stato di sincronizzazione iniziale di ogni tabella in una sottoscrizione nel catalogo di sistema pg_subscription_rel (cerca r =pronto nella colonna srsubstate ). Lo stato generale della replica può essere verificato in pg_stat_replication sul lato mittente e pg_stat_subscription sul lato ricevente.

9. Come accennato in precedenza, le modifiche alla sequenza non vengono replicate. Una possibile soluzione è copiare i valori della sequenza usando pg_dump. Puoi ottenere un dump dei valori della sequenza corrente usando qualcosa del genere:

pg_dump -d dbname --data-only -t '*_seq' >seq-data.sql

(Ciò presuppone che i nomi delle sequenze corrispondano tutti a *_seq e nessuna tabella corrisponde a quel nome. Nei casi più complicati potresti anche seguire la strada della creazione di un dump completo ed estrarre i dati della sequenza dal sommario del dump.)

Poiché le sequenze potrebbero avanzare mentre lo fai, forse munge il seq-data.sql file per aggiungere un po' di gioco ai numeri.

Quindi ripristina quel file nel nuovo database usando psql.

10. Showtime:passa le applicazioni alle nuove istanze. Ciò richiede un po' di riflessione in anticipo. Nello scenario più semplice, interrompi i programmi applicativi, modifichi le impostazioni di connessione, riavvii. Se utilizzi un proxy di connessione, puoi passare la connessione lì. Puoi anche cambiare le applicazioni client una per una, magari per testare un po' le cose o alleggerire il carico sul nuovo sistema. Funzionerà fintanto che le applicazioni che puntano ancora al vecchio server e quelle che puntano al nuovo server non effettuano scritture in conflitto. (In tal caso avresti in esecuzione un sistema multimaster, almeno per un breve periodo, e questo è un altro ordine di complessità.)

11. Al termine dell'aggiornamento, è possibile eliminare l'impostazione della replica. In ogni database sulla nuova istanza, esegui

DROP SUBSCRIPTION s_upgrade;

Se hai già spento la vecchia istanza, questo non riuscirà perché non sarà in grado di raggiungere il server remoto per eliminare lo slot di replica. Vedi la pagina man di DROP SUBSCRIPTION per come procedere in questa situazione.

Puoi anche eliminare le pubblicazioni sull'istanza di origine, ma ciò non è necessario poiché una pubblicazione non conserva alcuna risorsa.

12. Infine, rimuovi le vecchie istanze se non ti servono più.

Alcuni commenti aggiuntivi sulle soluzioni alternative per le cose che la replica logica non supporta. Se stai usando oggetti di grandi dimensioni, puoi spostarli usando pg_dump, ovviamente purché non cambino durante il processo di aggiornamento. Questa è una limitazione significativa, quindi se sei un utente pesante di oggetti di grandi dimensioni, questo metodo potrebbe non essere adatto a te. Se l'applicazione emette TRUNCATE durante il processo di aggiornamento, tali azioni non verranno replicate. Forse puoi modificare la tua applicazione per impedirgli di farlo per il momento dell'aggiornamento, oppure puoi sostituire un DELETE. PostgreSQL 11 supporterà la replica di TRUNCATE, ma funzionerà solo se sia l'istanza di origine che quella di destinazione sono PostgreSQL 11 o successive.

Alcuni commenti conclusivi che si applicano davvero a tutti gli impegni di aggiornamento:

  • Le applicazioni e tutti i programmi client del database devono essere testati rispetto a una nuova versione principale di PostgreSQL prima di essere messi in produzione.
  • A tal fine, dovresti anche testare la procedura di aggiornamento prima di eseguirla nell'ambiente di produzione.
  • Scrivi le cose o meglio script e automatizza il più possibile.
  • Assicurati che la configurazione del backup, i sistemi di monitoraggio e tutti gli strumenti e gli script di manutenzione siano regolati in modo appropriato durante la procedura di aggiornamento. Idealmente, questi dovrebbero essere a posto e verificati prima che il passaggio sia completato.

Con questo in mente, buona fortuna e condividi le tue esperienze.