Project

General

Profile

MySQLReplication » History » Version 31

Simone Piccardi, 12/29/2015 11:59 AM

1 1 japoco romagnoli
h1. Configurare la replicazione di MySQL
2 2 japoco romagnoli
3 19 Simone Piccardi
Occorrono almeno due installazioni indipendenti di MySQL, una macchina deve fare da master, le altre da slave. Inoltre non è possibile per fare da slave per master diversi, questo significa che se si devono replicare database che stanno su macchine diverse, queste dovranno essere replicata su istanze diverse.
4 2 japoco romagnoli
5 19 Simone Piccardi
Prenderemo in considerazione solo il caso elementare di due macchine. Le due istanze devono essere configurate per essere raggiungibili via rete. La replicazione si basa sul configurare il master per creare un log binario con le operazioni che vengono eseguite in scrittura. Lo slave leggendo i file su cui vengono registrate queste operazione le ripete su se stesso per “allinearsi”.
6 2 japoco romagnoli
7 19 Simone Piccardi
h2. Configurazione del Master
8 1 japoco romagnoli
9 19 Simone Piccardi
Il primo passo è la configurarazione del master, per questo occorre modificare il file @/etc/mysql/my.cnf@ per abilitare la connessione via rete e la scrittura del file di log binario. Le modifiche da effettuare prevedono linseremento delle seguenti configurazioni al posto di quelle installate normalmente dal pacchetto Debian di MySQL:
10 5 japoco romagnoli
11 3 japoco romagnoli
<pre>
12 3 japoco romagnoli
[...]
13 1 japoco romagnoli
bind-address	= 0.0.0.0
14 23 Simone Piccardi
# oppure
15 23 Simone Piccardi
# bind-address = IP.O.NOME.MASTER 
16 4 japoco romagnoli
[...]
17 1 japoco romagnoli
server-id = 1
18 3 japoco romagnoli
log_bin = /var/log/mysql/mysql-bin.log
19 3 japoco romagnoli
expire_logs_days = 10
20 6 japoco romagnoli
max_binlog_size = 100M
21 1 japoco romagnoli
[...]
22 5 japoco romagnoli
</pre>
23 5 japoco romagnoli
24 23 Simone Piccardi
(qualora si voglia usare un IP specifico per @bind-address@ invece di quello generico, è in genere preferibile utilizzare un nome a dominio opportunamente risolto invece del valore numerico, il valore di @server-id@ è arbitrario, ma deve essere diverso per tutte le istanze).
25 20 Simone Piccardi
26 19 Simone Piccardi
Qualora si siano fatti tentativi precedenti, per ripartire da zero, è necessario cancellare eventuali vecchi file di log binario, in modo tale che il server crei un log pulito a prova di errore, con:
27 5 japoco romagnoli
28 5 japoco romagnoli
<pre>
29 5 japoco romagnoli
rm /var/log/mysql/mysql-bin.*
30 5 japoco romagnoli
</pre>
31 5 japoco romagnoli
32 19 Simone Piccardi
si provveda poi a riavviare il server MySQL, in modo che prenda le nuove configurazioni:
33 5 japoco romagnoli
34 1 japoco romagnoli
<pre>
35 19 Simone Piccardi
service mysql restart
36 1 japoco romagnoli
</pre>
37 5 japoco romagnoli
38 19 Simone Piccardi
A questo punto si dovrà impostare MySQL per abilitare un utente con accesso da remoto che possa leggere i log ed eseguire la replicazione, l'utente deve essere definito sul master, e sarà usato dagli slave per connettersi, questo si fa collegandosi con @mysql@ ed eseguendo il codice SQL:
39 6 japoco romagnoli
40 1 japoco romagnoli
<pre>
41 23 Simone Piccardi
GRANT REPLICATION SLAVE ON *.* TO 'utentereplicazione'@'IP.O.NOME.SLAVE' IDENTIFIED BY 'passwordlungaecomplicata';
42 1 japoco romagnoli
FLUSH PRIVILEGES;
43 8 japoco romagnoli
</pre>
44 8 japoco romagnoli
45 19 Simone Piccardi
Una volta attive le nuove configurazioni occorre trasferire i dati dal master allo slave per l'importazione iniziale. Questi devono essere in uno stato coerente per cui non è possibile eseguire operazioni sul database durante la sincronizzazione iniziale. Pur essendo possibile far eseguire tutta la transazione via rete, per mantenerla in stato coerente questa necessita di mantenere un lock sul database per tutto il tempo impiegato a replicare i dati, che con database popolati significativamente può essere anche molto lungo. 
46 8 japoco romagnoli
47 19 Simone Piccardi
Per questo è in genere preferibile fare un dump ad un certo momento e per ripartire dallo stato in cui lo si era fatto. In questo caso il lock è necessario solo per il tempo, in genere molto minore, in cui si crea il dump. Una volta effettuato il dump si potrà rimuovere il blocco e indicare allo slave, una volta importato il dump, di ripartire dal punto in cui questo era stato fatto usando le informazioni registrate sul file di log mantenuto dal master.  
48 7 japoco romagnoli
49 19 Simone Piccardi
Per far questo si deve collegarsi sulla CLI di MySQL, selezionare il database da replicare e bloccare le tabelle in scrittura, così da avere uno stato coerente dei dati, con le istruzioni:
50 19 Simone Piccardi
51 6 japoco romagnoli
<pre>
52 6 japoco romagnoli
USE nome_database
53 6 japoco romagnoli
FLUSH TABLES WITH READ LOCK;
54 6 japoco romagnoli
</pre>
55 6 japoco romagnoli
56 19 Simone Piccardi
Si dovrà poi controllare lo stato del master (che ci servirà per stabilire il punto da cui far ripartire la replicazione sullo slave) con il comando @SHOW MASTER STATUS@, questo darà un risultato del tipo:
57 6 japoco romagnoli
58 6 japoco romagnoli
<pre>
59 1 japoco romagnoli
mysql> SHOW MASTER STATUS;
60 24 Simone Piccardi
+------------------+----------+--------------+------------------+
61 24 Simone Piccardi
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
62 24 Simone Piccardi
+------------------+----------+--------------+------------------+
63 24 Simone Piccardi
| mysql-bin.000005 | 13955148 |              |                  |
64 24 Simone Piccardi
+------------------+----------+--------------+------------------+
65 6 japoco romagnoli
1 row in set (0.00 sec)
66 1 japoco romagnoli
</pre>
67 6 japoco romagnoli
68 6 japoco romagnoli
A questo punto, senza chiudere la shell di MySQL (per evitare di perdere il lock sulle tabelle), si effettui il dump del database su un file @.sql@ da trasferire sul server slave con:
69 1 japoco romagnoli
70 6 japoco romagnoli
<pre>
71 20 Simone Piccardi
mysqldump -u root nome_database_da_replicare > dati_database.sql
72 6 japoco romagnoli
</pre>
73 6 japoco romagnoli
74 19 Simone Piccardi
una volta finita l'esportazione potremo tornare sulla shell di MySQL e sbloccare il lock in lettura con:
75 11 japoco romagnoli
76 6 japoco romagnoli
<pre>
77 6 japoco romagnoli
UNLOCK TABLES;
78 6 japoco romagnoli
</pre>
79 1 japoco romagnoli
80 19 Simone Piccardi
A questo punto le operazioni sul master sono terminate, la scrittura riprenderà, ma essendo registrata nel log lo slave sarà in grado di ripartire senza problemi utilizzando il punto di partenza indicato dai risultati di @SHOW MASTER STATUS@.
81 1 japoco romagnoli
82 16 japoco romagnoli
83 19 Simone Piccardi
h2. Configurazione dello Slave
84 15 japoco romagnoli
85 19 Simone Piccardi
Anche in questo caso occorre riconfigurare il server MySQL, in particolare occorrerà assegnargli un diverso @server-id@ ed inoltre occorrerà spostare @tmpdir@ su una directory il cui contenuto sia garantito in caso di riavvio, in quanto la cancellazione dei file temporanei potrebbe compromettere l'aggiornamento della replicazione. Rispetto al file di configurazione standard occorrerà apportare le seguenti modifiche:
86 1 japoco romagnoli
87 1 japoco romagnoli
<pre>
88 1 japoco romagnoli
[...]
89 1 japoco romagnoli
tmpdir          = /var/tmp
90 1 japoco romagnoli
[...]
91 12 japoco romagnoli
bind-address	= 0.0.0.0
92 23 Simone Piccardi
# oppure
93 1 japoco romagnoli
# bind-address = IP.O.NOME.SLAVE 
94 1 japoco romagnoli
[...]
95 23 Simone Piccardi
server-id = 2
96 6 japoco romagnoli
log_bin = /var/log/mysql/mysql-bin.log
97 6 japoco romagnoli
expire_logs_days = 10
98 1 japoco romagnoli
max_binlog_size = 100M
99 24 Simone Piccardi
replicate_wild_do_table = database_da_replicare.%
100 24 Simone Piccardi
replicate_wild_do_table = altrodb_da_replicare.%
101 1 japoco romagnoli
[...]
102 6 japoco romagnoli
</pre>
103 6 japoco romagnoli
104 23 Simone Piccardi
(di nuovo qualora si voglia usare un IP specifico per @bind-address@ è preferibile utilizzare un nome a dominio opportunamente risolto invece del valore numerico, ed il valore di @server-id@ è arbitrario, ma deve essere diverso da quello del master e di altri eventuali slave).
105 7 japoco romagnoli
106 23 Simone Piccardi
A questo punto si dovrà rendere effettive le nuovo configurazioni riavviando il server MySQL anche sulla macchina slave:
107 23 Simone Piccardi
108 13 japoco romagnoli
<pre>
109 13 japoco romagnoli
service mysql restart
110 13 japoco romagnoli
</pre>
111 13 japoco romagnoli
112 13 japoco romagnoli
113 19 Simone Piccardi
Per l'importazione iniziale dei dati occorrerà anzitutto creare sullo slave un database con lo stesso nome di quello che vogliamo replicare: 
114 19 Simone Piccardi
115 19 Simone Piccardi
<pre>
116 1 japoco romagnoli
mysqladmin -u root -p create nome_database_da_replicare
117 7 japoco romagnoli
</pre>
118 1 japoco romagnoli
119 1 japoco romagnoli
a questo punto si potranno caricare i dati dal file con il dump ottenuto sul master con:
120 7 japoco romagnoli
121 1 japoco romagnoli
<pre>
122 1 japoco romagnoli
mysql nome_database_da_replicare < dati_database.sql
123 1 japoco romagnoli
</pre>
124 1 japoco romagnoli
125 23 Simone Piccardi
Si verifichi inoltre che l'utente di replicazione impostato sul master sia effettivamente utilizzabile, per questo basterà effettuare una connessione verso il master con:
126 1 japoco romagnoli
127 23 Simone Piccardi
<pre>
128 23 Simone Piccardi
mysql -h IP.O.NOME.MASTER -u utentereplicazione -p
129 23 Simone Piccardi
</pre>
130 23 Simone Piccardi
131 23 Simone Piccardi
(usando la password impostata in precedenza).
132 23 Simone Piccardi
133 29 Simone Piccardi
L'ultimo passo è impostare il server come slave, questo richiede che si usino le credenziali dell'utente creato in precedenza sul master, e che si indichi anche, utilizzando i dati ottenuti dal precedente comando @SHOW MASTER STATUS@, il riferimento da cui partire nei log per proseguire con la replicazione (questo è essenziale perché lo slave possa sincronizzarsi correttamente). Facendo riferimento a quanto ottenuto nel paragrafo precedente si dovrà pertanto eseguire sulla CLI di MySQL la seguente istruzione:
134 20 Simone Piccardi
135 1 japoco romagnoli
<pre>
136 23 Simone Piccardi
CHANGE MASTER TO master_host='IP.O.NOME.MASTER', master_user='utentereplicazione', 
137 21 Simone Piccardi
master_port=3306, master_password='passwordlungaecomplicata', master_log_file='mysql-bin.000005', 
138 21 Simone Piccardi
master_log_pos=13955148;
139 1 japoco romagnoli
START SLAVE;
140 17 japoco romagnoli
</pre>
141 1 japoco romagnoli
142 21 Simone Piccardi
dove appunto mysql-bin.000005 e 13955148 sono rispettivamente il file di log e la posizione riportati da @SHOW MASTER STATUS@.
143 11 japoco romagnoli
144 20 Simone Piccardi
Fatto questo si potrà controllare lo status dello slave da MySQL con il comando, e verificare che questo venga aggiornato in corrispondenza a quanto ottenuto con @SHOW MASTER STATUS@:
145 20 Simone Piccardi
146 17 japoco romagnoli
<pre>
147 25 Simone Piccardi
SHOW SLAVE STATUS \G;
148 17 japoco romagnoli
</pre>
149 11 japoco romagnoli
150 28 Simone Piccardi
e rieseguendolo più volte si noterà che in particolare la riga:
151 17 japoco romagnoli
152 28 Simone Piccardi
<pre>
153 28 Simone Piccardi
...
154 28 Simone Piccardi
        Seconds_Behind_Master: 53394
155 28 Simone Piccardi
...
156 28 Simone Piccardi
</pre>
157 28 Simone Piccardi
158 28 Simone Piccardi
avrà un valore in progressiva riduzione via via che la replicazione prosegue fino ad attestarsi ad un valore nullo.
159 28 Simone Piccardi
160 28 Simone Piccardi
161 20 Simone Piccardi
h2. Trasformare lo slave in master
162 1 japoco romagnoli
163 30 Simone Piccardi
Volendo cambiare il nostro server slave nel nuovo master il primo passo da fare è assicurarsi che questo sia il più aggiornato possibile. Se il master è irraggiungibile, questo può essere fatto, nel caso di più slave, selezionando eventualmente quello più aggiornato (se ne esiste uno)  verificando il progresso con @SHOW SLAVE STATUS \G@ sulla riga _"Read_Master_Log_Pos"_; se il master è attivo, occorre anzitutto assicurarsi che vengano scaricati i log pendenti eseguendo su di esso:
164 20 Simone Piccardi
165 1 japoco romagnoli
<pre>
166 30 Simone Piccardi
FLUSH LOGS;
167 30 Simone Piccardi
</pre>
168 30 Simone Piccardi
169 30 Simone Piccardi
inoltre occorre eseguire sugli slave:
170 30 Simone Piccardi
171 30 Simone Piccardi
<pre>
172 30 Simone Piccardi
STOP SLAVE IO_THREAD;
173 30 Simone Piccardi
</pre>
174 30 Simone Piccardi
175 30 Simone Piccardi
e verificare che nell'output di @SHOW PROCESSLIST@ sia riportato ''Has read all relay log''.
176 30 Simone Piccardi
177 31 Simone Piccardi
Una volta che si sia fermato il master, o se ne sia comunque bloccata la modifica dei dati, si deve andare a cambiare il file @/etc/mysql/my.cnf@ dello slave controllando che siano abilitate le opzioni di @log-bin@ e disabilitato tutto quello che riguarda i log del tipo @slave-updates@. Si deve anche verificare che il @bind-address@ sia effettivamente impostato su @0.0.0.0@ permettendo così il raggiungimento della macchina dalla rete, la configurazione sarà pertanto qualcosa del tipo:
178 30 Simone Piccardi
179 30 Simone Piccardi
<pre>
180 17 japoco romagnoli
[...]
181 17 japoco romagnoli
bind-address	= 0.0.0.0
182 1 japoco romagnoli
[...]
183 30 Simone Piccardi
server-id = 2
184 17 japoco romagnoli
log_bin = /var/log/mysql/mysql-bin.log
185 1 japoco romagnoli
expire_logs_days = 10
186 17 japoco romagnoli
max_binlog_size = 100M
187 17 japoco romagnoli
[...]
188 17 japoco romagnoli
</pre>
189 1 japoco romagnoli
190 30 Simone Piccardi
in particolare è il caso di eliminare le eventuali direttive @replicate_wild_do_table@ inserite per limitare i database da cui si effettua la replicazione, mentre non serve cambiare il valore di @server-id@.
191 30 Simone Piccardi
192 17 japoco romagnoli
A questo punto, entrando in MySQL, si può fermate il server slave e reimpostarlo come nuovo master:
193 17 japoco romagnoli
194 18 japoco romagnoli
<pre>
195 1 japoco romagnoli
STOP SLAVE;
196 1 japoco romagnoli
RESET MASTER;
197 31 Simone Piccardi
</pre>
198 31 Simone Piccardi
199 31 Simone Piccardi
occorrerà infine abilitare un utente per la replicazione in maniera analoga a quanto fatto nella creazione del master con:
200 31 Simone Piccardi
201 31 Simone Piccardi
<pre>
202 31 Simone Piccardi
GRANT REPLICATION SLAVE ON *.* TO 'utentereplicazione'@'IP.O.NOME.SLAVE' IDENTIFIED BY 'passwordlungaecomplicata';
203 31 Simone Piccardi
FLUSH PRIVILEGES;
204 1 japoco romagnoli
</pre>
205 1 japoco romagnoli
206 30 Simone Piccardi
Volendo reimpostare l'ormai defunto master nel nuovo slave che replichi il nuovo master, dovremo inserire nel suo @my.cnf@ le @replicate_wild_do_table@ tolte dallo slave, e seguire la procedura seguente per riallineare uno slave, facendo riferimento a quello che ora è diventato il nuovo master.
207 26 Simone Piccardi
208 26 Simone Piccardi
209 25 Simone Piccardi
h2. Riallineare uno slave
210 1 japoco romagnoli
211 28 Simone Piccardi
Qualora la replicazione si sia interrotta (cosa che può accadere se ad esempio l'istanza replicata resta ferma per un numero di giorni superiore a quello indicato dalla direttiva @expire_logs_days@ del @my.cnf@ del master) si può effettuare un riallineamento manuale della stessa. La procedura è simile a quella della impostazione iniziale, occorre infatti ripetere un sottoinsieme dei passi. 
212 25 Simone Piccardi
213 27 Simone Piccardi
La prima fase è quella di ottenere, con la stessa procedura descritta in precedenza, un dump dell'istanza principale conoscendo lo stato del master in quel momento: occorrerà pertanto selezionare il database, bloccarne le tabelle con @FLUSH TABLES WITH READ LOCK;@ ed ottenere lo stato corrente del master con @SHOW MASTER STATUS;@ (segnandosi i numeri del file di log e della posizione corrente) mentre al contempo, senza uscire dalla shell di @mysql@ per mantenere il lock sulle tabelle, si eseguirà il dump del database. 
214 25 Simone Piccardi
215 27 Simone Piccardi
Una volta eseguito il dump si potrà rilasciare il lock (o esplicitamente con @UNLOCK TABLES@ o abbandonando la shell). Dopo di che, copiato il dump sull'istanza slave lo si potrà reimportare eliminando i dati correnti. In questo caso si dovrà preventivamente bloccare la replicazione con il comando:
216 25 Simone Piccardi
217 25 Simone Piccardi
<pre>
218 25 Simone Piccardi
STOP SLAVE;
219 25 Simone Piccardi
</pre>
220 25 Simone Piccardi
221 25 Simone Piccardi
e poi eseguire il caricamento dei dati allo stato noto con:
222 25 Simone Piccardi
223 25 Simone Piccardi
<pre>
224 25 Simone Piccardi
mysql nome_database_da_replicare < dump_del_database.sql
225 25 Simone Piccardi
</pre>
226 25 Simone Piccardi
227 25 Simone Piccardi
e a questo punto basterà ricollegarsi all'istanza secondaria e ripetere una istruzione @CHANGE MASTER@ identica a quella già illustrata usando il file di log e la posizione segnata in precedenza, infine si farà ripartire la replicazione con: 
228 25 Simone Piccardi
229 25 Simone Piccardi
<pre>
230 25 Simone Piccardi
START SLAVE;
231 1 japoco romagnoli
</pre>
232 25 Simone Piccardi
233 28 Simone Piccardi
e si potrà controllare che tutto sia a posta con @SHOW SLAVE STATUS \G@ verificando che la replicazione stia aggiornando i dati della posizione del master e che la voce ''Seconds_Behind_Master'' si riduca progressivamente fino ad annullarsi.