Progetto

Generale

Profilo

PostgresStreamReplication » Cronologia » Versione 5

Versione 4 (Simone Piccardi, 12-05-2022 15:01) → Versione 5/6 (Simone Piccardi, 12-05-2022 15:15)

h1. Replicazione di PostgresSQL 

 *ATTENZIONE*: questo articolo è una bozza, al momento è nello stato di insieme di appunti sparsi senza un'ordine specifico 

 PostgreSQL supporta diversi meccanismi di replicazione, tratteremo in questo articolo solo uno di questi, la cosiddetta _streaming replication_.  

 h2. Come ripristinare una replica 

 Se per un qualunque motivo la _streaming replication_ si interrompe (la ragione più comune è che non si è previsto sul primario la retention di un sufficiente numero di segmenti WAL a coprire le differenze da trasmettere al secondario) occorre ripristinare manualmente da zero la stessa. Per questo motivo è sempre opportuno abilitare sul master l'uso di un _replication slot_ . 

 Per farlo è disponibile, a partire dalla versione 9.4 di PostgreSQL il comando @pg_basebackup@ (si legga la documentazione su https://www.postgresql.org/docs/10/app-pgbasebackup.html) che consente di eseguire il ripristino direttamente dal secondario. I passi da seguire per farlo sono i seguenti: 

 * fermare Postgres con: 
 <pre> 
 service postgresql stop 
 </pre> 
 * vuotare la directory dei dati (o spostarne i contenuti altrove): 
 <pre> 
 mkdir oldpgdir/ 
 mv /var/lib/postgresql/9.6/main/* oldpgdir/ 
 </pre> 
 * collegarsi con l'utente postgres: 
 <pre> 
 su postgres 
 </pre> 
 * ripristinare il DB e la replicazione con: 
 <pre> 
 pg_basebackup -h IP.DEL.DB.MASTER -U replication -D /var/lib/postgresql/9.6/main/ -P -Xs -R -S 'slot_name' 
 </pre> 
 quest'ultimo comando chiederà la password dell'utente @replication@ usato per gestire la replicazione e provvederà alla ricostruzione (si ometta @-S 'slot_name'@ se non si è creato un _replication slot_) . 
 * riavviare Postgres con: 
 <pre> 
 service postgresql start 
 </pre> 

 h2. Verifica dello stato della replicazione 

 Ci sono una serie di comandi per verificare lo stato della replicazione. Anzitutto si vada sullo slave e si verifichi che sia in standby    mode con (si assume di essere entrati in visualizzazione espansa con @\x on@): 

 <pre> 
 postgres=# SELECT pg_is_in_recovery(); 
 -[ RECORD 1 ]-----+-- 
 pg_is_in_recovery | t 
 </pre>  

 si può controllare lo stato della ricezione dei dati dal master (da postgres 9.6) con: 

 <pre> 
 postgres=# select * from pg_stat_wal_receiver; 
 -[ RECORD 1 ]---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
 pid                     | 25684 
 status                  | streaming 
 receive_start_lsn       | 7E/57000000 
 receive_start_tli       | 1 
 received_lsn            | 7E/58B33BA8 
 received_tli            | 1 
 last_msg_send_time      | 2020-02-19 17:57:20.239628+01 
 last_msg_receipt_time | 2020-02-19 17:57:20.238761+01 
 latest_end_lsn          | 7E/58B33BA8 
 latest_end_time         | 2020-02-19 17:57:20.239628+01 
 slot_name               |  
 conninfo                | user=replication password=******** .... 
 </pre> 

 e si può controllare quanto è passato dall'ultimo replay della replicazione con con: 

 <pre> 
 postgres=# select now()-pg_last_xact_replay_timestamp(); 
 -[ RECORD 1 ]------------ 
 ?column? | 00:00:05.55037 
 </pre> 

 ma questa indicazione, se non è successo nulla sul master, non è significativa, perché registra solo quando è stata fatta l'ultima modifica rispetto ad adesso, che può essere avvenuto anche parecchio indietro nel tempo se nel frattempo non c'era nulla da modificare. 

 Per e dare una indicazione dell'eventuale ritardo rispetto al master si può (su postgres 9.6) usare qualcosa del tipo: con: 

 <pre> 
 postgres=# SELECT CASE WHEN pg_last_xlog_receive_location() = pg_last_xlog_replay_location() 
                   THEN 0 
                 ELSE EXTRACT (EPOCH FROM now() - pg_last_xact_replay_timestamp()) 
               END AS log_delay; 
 -[ RECORD 1 ] 
 log_delay | 0 
 </pre> 

 mentre a partire da postgres 10 (i nomi delle funzioni sono cambiati) si può usare: 

 <pre> 
 SELECT CASE WHEN pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn()                         
                   THEN 0                                                                          ELSE EXTRACT (EPOCH FROM now() - pg_last_xact_replay_timestamp())                               
               END AS log_delay; 
 </pre>