Dato che ho necessità di fare questa operazione per lavoro, colgo l’occasione per scrivere un articolo che serva come guida per aggiungere un server slave a mysql per la replicazione del database. Avere uno slave mysql può servire per vari motivi, ad esempio bilanciare il carico delle query in lettura, o semplicemente fare una copia di backup del database mysql. Da sottolineare “in lettura“, dal momento che le query in scrittura vanno necessariamente lanciate sul server master, perchè di default la replicazione di mysql è oneway, cioè solo in un senso e asincrona, sebbene l’intervallo di tempo sia comunque molto basso (nell’ordine dei millisecondi). In altre parole, si imposta un server mysql come master, gli si dice di creare un log binario con le operazioni che vengono eseguire in scrittura, e poi lo slave leggendo il file di log, ripete le stesse operazioni su se stesso per “allinearsi”. Il viceversa non vale. Diverso è il caso della configurazione mysql multimaster, ma tratterò l’argomento in un altro articolo successivo.
Ok, passiamo alla pratica: come aggiungere uno slave ad un server mysql esistente. Inutile dire che tutte le operazioni banno eseguite con la massima attenzione e con mysql fermo o almeno bloccato in sola lettura per non fare danni.
Prima di tutto bisogna configurare il server mysql esistente come master:
/etc/init.d/mysql stop
Modificare il file /etc/mysql/my.cnf per abilitare il networking e la scrittura del file di log binario:
#skip-networking
bind-address = [indirizzo_ip_raggiungibile_dal_server_slave]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
binlog_do_db = [nome_db_da_replicare]
Adesso per sicurezza, cancelliamo eventuali vecchi file di log binario (così il server crea un log pulito ed a prova di errore) e poi facciamo ripartire il server master:
rm /var/log/mysql/mysql-bin.*
/etc/init.d/mysql start
Ripartito il server, accediamo via consolle a MySQL:
mysql -u root -p
E diciamo a MySQL di consentire la replica al nostro slave:
GRANT REPLICATION SLAVE ON *.* TO '[nome_utente]'@'[indirizzo_ip_dello_slave]' IDENTIFIED BY '[password]';
FLUSH PRIVILEGES;
Ora bisogna selezionare il database da replicare e impostare eventuali lock di lettura per spostare i dati (se presenti) dal master allo slave:
USE [nome_database];
FLUSH TABLES WITH READ LOCK;
Controlliamo lo stato del master:
SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 98 | [nome_db] | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
Bene, adesso senza chiudere la shell di MySQL (altrimenti perdiamo il lock sulle tabelle e bisogna ricominciare), apriamo un’altra shell ed esportiamo il database in un file sql da traferire sul server slave:
mysqldump -u root -p --opt [nome_db] > [nome_db].sql
Una volta finita l’esportazione possiamo riaprire la shell di mysql per sbloccare il lock in lettura:
UNLOCK TABLES;
Ok, passiamo alla configurazione del server slave di mysql
Prima di tutto bisogna creare il database da replicare, quindi nella consolle dello slave MySQL scriviamo:
mysql -u root -p
Enter password:
CREATE DATABASE [nome_db];
quit;
Ora carichiamo il dump SQL che abbiamo fatto prima dal server master mysql:
mysql -u root -p [nome_db] < [path_dove_e_salvato_il_file]/[nome_db].sql
Modificare il file /etc/mysql/my.cnf per abilitare la lettura del file di log del server master:
server-id=2
master-host=[ip_master]
master-user=[user_creato_sul_master]
master-password=[password]
master-connect-retry=60
replicate-do-db=[nome_db]
A meno che lo slave sia un master a sua volta per altri slave sotto di lui, possiamo commentare la parte per il log bin sul server slave.
Ora non resta che riavviare il demone di mysql anche sullo slave e speriare che sia andato tutto bene 🙂
/etc/init.d/mysql restart
Per controllare lo status dello slave (va fatto periodicamente per assicurarci che funzioni!!) si può usare questo comando:
SLAVE STATUS;
That’s all folks!
—–
PRECISAZIONE:
Nel caso la replicazione debba partire da un una particolare posizione del log binario di mysql, bisogna lanciare il seguente comando nella shell di mysql:
CHANGE MASTER TO MASTER_HOST='<master_host_name>', MASTER_USER='<slave_user>', MASTER_PASSWORD='<slave_password>', MASTER_LOG_FILE='<recorded_log_file_name>', MASTER_LOG_POS=<recorded_log_position>
Successivamente, se necessario, adeguare la configurazione nel file /etc/mysql/my.cnf.
—–
AGGIORNAMENTO:
Nel caso il DB sia troppo grande, o comunque si voglia replicare l’intero server, procedere come segue (ovviamente dopo avere fermato mysql sia sul master che sullo slave, mi raccomando!):
server master:
1. Ferma MySql
sudo /etc/init.d/mysql stop
2. Compatta tutti i dati
tar zcvf mysql.tgz /var/lib/mysql
3. Copia (possibilmente con scp o comunque via SSH) il file mysql.tgz nello slave
4. Riavvia MySql
sudo /etc/init.d/mysql start
server slave:
1. Ferma MySql
sudo /etc/init.d/mysql stop
2. Rimuovi la cartella dei dati attuale
sudo rm -rf /var/lib/mysql
3. Scompatta la versione nuova dei dati
sudo tar zxvf mysql.tgz
4. Riavvia il database
sudo /etc/init.d/mysql start
Ciao ho seguito altre guide simili alla tua, tutto va bene solo che vengono replicati solo i cambiamenti effettuati sulle tabelle del db ma i dati non vengono aggiornati.
Ti faccio un esempio:
Sul master ho aggiunto la tabella xxx che non c’è nello slave, controllo lo slave e la tabella è stata creata con successo, ma resta vuota cioè tutti i record inseriti nel master non vengono replicati nello slave.
Se puoi aiutarmi te ne sarei grato.
Ciao
Ps. Tra l’altro, adesso che vedo, sono un tuo compaesano…