Ciao,
ho installato un server mysql slave per effettuare una replica del database corrente.
In rete ci sono tantissimi howto che spiegano come fare ma la maggior parte di essi prevede due condizioni:
a) l’ uso del FLUSH TABLES WITH READ LOCK (ciò significa che mysql, non scriverà nel database i dati ma li memorizzerà in memoria fino a quando non sbloccheremo le tabelle) che, in termini pratici, vuol dire avere un database “congelato” e di conseguenza un sito bloccato.
b) l’installazione di entrambi i database (master e slave) da zero.
..e se, come nel mio caso, non posso fermare il database e ho l’ esigenza di aggiungere un server slave all’ attuale, che diventerà master? Ora vi spiego come fare. (La guida è stata testata su Debian 7, ma funziona anche per altri sistemi, abbiate la cortezza di individuare i path corretti dei vari files)
Cominciamo dal master:
vi /etc/mysql/my.cnf
Aggiungiamo:
server-id=1 log_bin = /var/log/mysql/mysql-bin.log binlog-format = mixed innodb_flush_log_at_trx_commit=1 sync_binlog = 1 expire_logs_days = 1 max_binlog_size = 100M binlog_do_db = <nome_database_da_replicare>
ed eliminiamo
bind-address = 127.0.0.1
oppure modifichiamolo con
bind-address = <ip_del_server>
ed assicuriamoci che il parametro
skip-networking
sia commentato/cancellato.
Vediamo nello specifico a cosa servono questi parametri:
- ser ver-id-> è un id univoco, utilizzato per la replica
- log-bin -> indica la directory dove vengono salvati i file bin-log
- binlog-format -> il formato in cui vengono scritti i log. Può essere RAW, STATEMENT e MIXED (per appronfondire http://dev.mysql.com/doc/refman/5.1/en/binary-log-setting.html)
- innodb_flush_log_at_trx_commit -> in una configurazione master/slave, viene consigliato di utilizzare 1 ( verificare http://dev.mysql.com/doc/refman/4.1/en/innodb-parameters.html). Lo stesso per il parametro sync_binlog
- expire_days -> indica dopo quanto tempo i binlog verranno cancellati
- max_binlog_size -> la dimensione massima di ciascun binlog file
- binlog_do_db -> il nome del database da replicare
Creiamo ora un utente dedicato da utilizzare per la replica (potete anche non farlo)
CREATE USER replicant@; GRANT REPLICATION SLAVE ON *.* TO replicant@ IDENTIFIED BY 'yourpassword';
ed ora il dump del database che vogliamo replicare:
mysqldump --skip-lock-tables --single-transaction --flush-logs --hex-blob --master-data=2 <nome_database> > db.sql
Eseguiamo il comando
grep "MASTER_LOG_POS" db.sql
e prendiamo nota della riga, ci servirà successivamente. Nel mio caso era:
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=107;
Portiamo il nostro database ‘db.sql’ sul server slave
scp db.sql@<slave_server>:/path
Passiamo ora alla configurazione dello slave.
vi /etc/mysql/my.cnf
Modificatelo, aggiungendo:
server-id = 2 binlog-format = mixed log_bin = /var/log/mysql/mysql-bin relay-log = /var/log/mysql/mysql-relay-bin log-slave-updates = 1 read-only = 1 expire_logs_days = 1 max_binlog_size = 100M
Riavviamo mysql
service mysql restart
Importiamo il dump
mysql -u root -p < db.sql
Diciamo allo slave quali sono le coordinate del master:
mysql -u root -p
Una volta che siete dentro mysql:
CHANGE MASTER TO MASTER_HOST='',MASTER_USER='replicant',MASTER_PASSWORD=' ', MASTER_LOG_FILE='<il_valore_fornito_dalla_grep_precedente>', MASTER_LOG_POS=<il_valore_fornito_dalla_grep_precedente>; START SLAVE;
Controllate lo stato dello slave con:
SHOW SLAVE STATUS \G;
Dovreste ottenere, tra le tante righe:
Waiting for master to send event
Verificate anche che i vari “Last_Error*” siano a 0 o vuoti
Qualche volta può succudere, per alcuni motivi tipo la modifica del dato direttamente sullo slave, che si perda la sincronia. In questo caso potete far ripartire lo slave così:
STOP SLAVE;SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;START SLAVE;
Test finale.
Provate a creare una tabella sul master:
create table test(id int not null auto_increment, primary key(id), username varchar(30) not null);
Ora spostatevi sullo slave è digitate:
select * from test;
Se risponde che la tabella è vuota, siete a posto!
Se invece vi dice che la tabella non esiste, la replica non sta funzionando.
Ultimissima cosa: su server mysql di grandi dimensioni, i binlog occuperanno molto spazio disco e può non essere sufficiente eliminari una volta al giorno.
Difatti, sul mio database server di circa 2 Gb, arrivo quasi a 100 Gb di bin-log al giorno.
Ho creato uno script, messo a crontab ogni 6 ore, che pulisce i binlog:
#!/bin/bash mysql -uroot -plavostrapassword -bse 'show binary logs;' > /tmp/binary.log lastline=`tail -n5 /tmp/binary.log|head -1 |awk '{print $1}'` mysql -uroot -plavostrapassword -bse "purge binary logs to '"$lastline"';" rm /tmp/binary.log
Abbiamo finito. Se qualcosa non è chiaro o avete domande/suggerimenti, lasciate un commento.
Fabrizio Regalli su Google+