Progetto

Generale

Profilo

PostgresStreamReplication » Cronologia » Versione 5

Simone Piccardi, 12-05-2022 15:15

1 1 Simone Piccardi
h1. Replicazione di PostgresSQL
2
3
*ATTENZIONE*: questo articolo è una bozza, al momento è nello stato di insieme di appunti sparsi senza un'ordine specifico
4
5
PostgreSQL supporta diversi meccanismi di replicazione, tratteremo in questo articolo solo uno di questi, la cosiddetta _streaming replication_. 
6
7
h2. Come ripristinare una replica
8
9 5 Simone Piccardi
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_ .
10 1 Simone Piccardi
11
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:
12
13 2 Simone Piccardi
* fermare Postgres con:
14 1 Simone Piccardi
<pre>
15
service postgresql stop
16
</pre>
17
* vuotare la directory dei dati (o spostarne i contenuti altrove):
18
<pre>
19
mkdir oldpgdir/
20
mv /var/lib/postgresql/9.6/main/* oldpgdir/
21
</pre>
22
* collegarsi con l'utente postgres:
23
<pre>
24
su postgres
25
</pre>
26
* ripristinare il DB e la replicazione con:
27
<pre>
28 3 Simone Piccardi
pg_basebackup -h IP.DEL.DB.MASTER -U replication -D /var/lib/postgresql/9.6/main/ -P -Xs -R -S 'slot_name'
29 1 Simone Piccardi
</pre>
30 4 Simone Piccardi
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_) .
31 2 Simone Piccardi
* riavviare Postgres con:
32
<pre>
33
service postgresql start
34
</pre>
35
36
h2. Verifica dello stato della replicazione
37
38 1 Simone Piccardi
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@):
39 2 Simone Piccardi
40
<pre>
41 3 Simone Piccardi
postgres=# SELECT pg_is_in_recovery();
42 2 Simone Piccardi
-[ RECORD 1 ]-----+--
43
pg_is_in_recovery | t
44
</pre> 
45
46
si può controllare lo stato della ricezione dei dati dal master (da postgres 9.6) con:
47
48
<pre>
49
postgres=# select * from pg_stat_wal_receiver;
50
-[ RECORD 1 ]---------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
51
pid                   | 25684
52
status                | streaming
53
receive_start_lsn     | 7E/57000000
54
receive_start_tli     | 1
55
received_lsn          | 7E/58B33BA8
56
received_tli          | 1
57
last_msg_send_time    | 2020-02-19 17:57:20.239628+01
58
last_msg_receipt_time | 2020-02-19 17:57:20.238761+01
59
latest_end_lsn        | 7E/58B33BA8
60
latest_end_time       | 2020-02-19 17:57:20.239628+01
61
slot_name             | 
62
conninfo              | user=replication password=******** ....
63
</pre>
64
65 5 Simone Piccardi
e si può controllare quanto è passato dall'ultimo replay della replicazione con:
66 2 Simone Piccardi
67
<pre>
68
postgres=# select now()-pg_last_xact_replay_timestamp();
69
-[ RECORD 1 ]------------
70
?column? | 00:00:05.55037
71
</pre>
72 1 Simone Piccardi
73 5 Simone Piccardi
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.
74 2 Simone Piccardi
75 5 Simone Piccardi
Per dare una indicazione dell'eventuale ritardo rispetto al master si può (su postgres 9.6) usare qualcosa del tipo:
76
77 2 Simone Piccardi
<pre>
78
postgres=# SELECT CASE WHEN pg_last_xlog_receive_location() = pg_last_xlog_replay_location()
79
                  THEN 0
80
                ELSE EXTRACT (EPOCH FROM now() - pg_last_xact_replay_timestamp())
81 1 Simone Piccardi
              END AS log_delay;
82
-[ RECORD 1 ]
83
log_delay | 0
84 5 Simone Piccardi
</pre>
85
86
mentre a partire da postgres 10 (i nomi delle funzioni sono cambiati) si può usare:
87
88
<pre>
89
SELECT CASE WHEN pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn()                        
90
                  THEN 0                                                                        ELSE EXTRACT (EPOCH FROM now() - pg_last_xact_replay_timestamp())                              
91
              END AS log_delay;
92 2 Simone Piccardi
</pre>