Oggi voglio pubblicare un qualcosa di interessante che mi è capitato per lavoro.
Ipotizziamo di avere 2 database MySQL in due zone geograficamente distanti tra loro.
Questi database devono essere consistenti, cioè contenere sempre gli stessi dati, così nel caso di perdita di connessione o di blocco del database 1 tutte le connessioni verranno indirizzate sul database 2 e viceversa.
Vi spiego meglio con una figura:
Abbiamo capito il problema, adesso vediamo come affrontarlo e trovare la soluzione.
In rete ho trovato molte “strade” più o meno simili, non è detto che la mia sia giusta, ma so che funziona perchè l’ho provata praticamente!
La soluzione che vi propongo è stata testata con mysql-server 5.5.37 su Debian 7.1 Wheezy a 64bit
Per prima cosa dobbiamo abilitare su entrambi i database il BINARY LOGGING che è un vero e proprio log delle operazioni che vengono effettuate su ogni database.
Modifichiamo il file di configurazione my.cnf come segue:
Database MASTER-1
server_id = 1
log_bin = /var/log/mysql/mysql-bin.log
log_bin_index = /var/log/mysql/mysql-bin.log.index
relay_log = /var/log/mysql/mysql-relay-bin
relay_log_index = /var/log/mysql/mysql-relay-bin.index
expire_logs_days = 10
max_binlog_size = 100M
log_slave_updates = 1
auto-increment-increment = 2
auto-increment-offset = 1
binlog_do_db = sharedb
Database MASTER-2
server_id = 2
log_bin = /var/log/mysql/mysql-bin.log
log_bin_index = /var/log/mysql/mysql-bin.log.index
relay_log = /var/log/mysql/mysql-relay-bin
relay_log_index = /var/log/mysql/mysql-relay-bin.index
expire_logs_days = 10
max_binlog_size = 100M
log_slave_updates = 1
auto-increment-increment = 2
auto-increment-offset = 2
binlog_do_db = sharedb
E’ molto importante definire il parametro auto-increment-offset diverso tra i due database, questo serve per evitare che ci siano conflitti di indici nelle fasi di replicazione.
Prima di riavviare il servizio, procediamo con la creazione/import del database sharedb su entrambi i server (ATTENZIONE consiglio che i databasesiano uguali in questa fase)
Sempre su entrambi i server, da console:
CREATE user 'replicante'@'%' IDENTIFIED BY 'Wp4Suppl1c4nt462!';
GRANT replication slave ON *.* TO 'replicante'@'%';
Riavviamo il servizio su entrambi i server.
Operiamo adesso sul server MASTER-1
mysql -u root - p
SHOW master STATUS;
Appare una cosa del genere:
+———————-+———-+——————-+———————–+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+———————-+———-+——————-+———————–+
| mysql-bin.000001 | 106 | sharedb | |
+———————-+———-+——————-+———————–+
Passiamo su MASTER-2
Da console sql:
slave stop;
CHANGE MASTER TO MASTER_HOST = 'IP-MASTER-1', MASTER_USER = 'replicante', MASTER_PASSWORD = 'Wp4Suppl1c4nt462!', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 106;
slave start;
SHOW master STATUS;
Apparirà quealcosa del genere:
+———————-+———-+——————-+———————–+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+———————-+———-+——————-+———————–+
| mysql-bin.000002 | 1060 | sharedb | |
+———————-+———-+——————-+———————–+
Torniamo su MASTER-1
Da console sql:
slave stop;
CHANGE MASTER TO MASTER_HOST = 'IP-MASTER-2', MASTER_USER = 'replicante', MASTER_PASSWORD = 'Wp4Suppl1c4nt462!', MASTER_LOG_FILE = 'mysql-bin.000002', MASTER_LOG_POS = 1060;
slave start;
Il gioco è fatto!
Proviamo a fare un update su uno dei due master e vedremo la replica in tempo (quasi reale!) sull’altro!
Per essere sicuri, da uno dei due server sempre da console fate un:
SHOW slave STATUS;
dovreste ottenere un qualcosa del genere:
……….Waiting for master to send event | IP-MASTER ………….
Enjoy!