Due server MySQL in replica circolare master-master

MySQL è un database relazionale, senza ombra di dubbio il più diffuso in assoluto, specie perchè presente di default su tutte le distribuzioni Linux e in tutte le configurazioni di webserver LAMP (Linux, Apache, Mysql, PHP).
Come già sostenuto precedentemente, il database MySQL è un ottimo componente, però il consumo di risorse può essere molto elevato nel caso in cui si eseguano delle query non ottimizzate. Tratteremo successivamente il tema dell’ottimizzazione delle query SQL, in questo articolo affronteremo il tema dal punto di vista sistemistico facendo “scalare” l’installazione di MySQL su due server in replica asincrona circolare (Master-Master).
Questa configurazione, oltre a raddoppiare la potenza di calcolo (come dice la pubblicità “du is megl che uan”), permette di avere una installazione totalemente fault-tolerant in quanto entrambi i server sono contemporaneamente “master e slave” l’uno dell’altro, quindi non c’è la necessità di dover promuovere uno slave a master in caso di guasto del primario.
Vedremo in un articolo successivo come è possibile scalare ulteriormente l’installazione, aggiungendo ulteriori server slave, il tutto utilizzando a monte un proxy MySQL per bilanciare il carico e gli script Mysql-MMM per gestire il funzionamento dei nodi.

Precisiamo due cose.
La prima è che è possibile configurare MySQL in modalità cluster NDB, una configurazione molto simile ad Oracle. In questo caso la possibilità di scalare è nettamente superiore, l’efficenza e la sicurezza sono incredibilmente elevate, però è possibile creare solo tabelle NDB, mentre MyISAM e InnoDB non sono supportati. Visto che la maggior parte delle applicazioni web “scarica, installa e usa” lavorano con tabelle MyISAM (prendiamo ad esempio Joomla e WordPress), l’utilizzo della modalità cluster mi è precluso.
La seconda è che è tecnicamente possibile avere un cluster “sincrono” di più server MySQL che fanno riferimento ad un unico storage condiviso contenente i dati (/var/lib/mysql). Per fare ciò è necessario che il filesystem cluster dello storage (tutti i nodi devono avere la possibilità di leggere e scrivere contemporaneamente, quindi è necessario un filesystem come GFS2 oppure OCFS2) abbia le funzionalità POSIX e che sia disabilitata la funzionalità “skip-external-locking” nella configurazione di MySQL. Così facendo si disabiliterà il metodo interno di locking dei dati, utilizzando il locking POSIX del filesystem; proprio per questo motivo non ho raggiunto risultati soddisfacenti sia in termini di velocità, sia intermini di stabilità del sistema, per cui preferisco lavorare con il vecchio e caro metodo asincrono.

Confgurazione del sistema

Partiamo dal presupposto di avere due installazioni di MySQL base e “vergini”. In questo caso utilizzo la distribuzione Ubuntu in cui è presente la directory /etc/mysql/conf.d/ nella quale inserire le configurazioni personalizzate del demone che vanno a sovrascrivere le impostazioni di default. In qualsiasi caso, la procedura di installazione è applicabile a qualsiasi distribuzione. Innanzi tutto modificare il file /etc/hosts mappando gli IP per server1.dominio.local e server2.dominio.local in modo da non dover far fare a MySQL inutili query DNS.
Quindi creare i seguenti file di configurazione:

Server 1:

<strong>/etc/mysql/conf.d/replica.cnf</strong>
[mysqld]
bind-address            = 0.0.0.0
server-id                       = 10
auto_increment_increment        = 10
auto_increment_offset           = 1
master-host                     = server2.dominio.local
master-user                     = replicauser
master-password                 = replicapass
log_bin             = /var/log/mysql/mysql-bin.log
binlog_ignore_db        = mysql

Server 2:

<strong>/etc/mysql/conf.d/replica.cnf</strong>
[mysqld]
bind-address            = 0.0.0.0
server-id                       = 20
auto_increment_increment        = 10
auto_increment_offset           = 2
master-host                     = server1.dominio.local
master-user                     = replicauser
master-password                 = replicapass
log_bin             = /var/log/mysql/mysql-bin.log
binlog_ignore_db        = mysql

Commentiamo assieme le configurazioni: abilito la possibilità di collegarsi a mysql tramite rete (riga 1), setto l’id univoco del server (riga 2), setto la modalità di gestione degli indici all’inserimento di un nuovo record in modo che gli id siano sempre unici (righe 3 e 4) – tralasciare questa configurazione porterebbe a problemi immensi, setto i dati di autenticazione del master (righe 4-5-6), abilito la scrittura dei log di replica (riga 7) e infine alla riga 8 escludo dalla replica il database mysql (opzionale).

Riavviamo su entrambi i server il servizio mysql ed entriamo in console mysql (mysq -p) per lanciare i seguenti comandi (sempre su entrambi i server):

create user 'replicauser'@'%.san.local' identified by 'replicapass';
grant replication slave on *.* to 'replicauser'@'%.dominio.local';
start slave;
show slave status\G;

Ecco fatto: l’installazione di mysql in replica è completata!