La funzionalita' di replica dati di
MySQL
e' semplice da configurare,
richiede poca manutenzione, e' molto flessibile
e non aggiunge carico al database Master:
tutto questo ne spiega la forte diffusione.
La gestione del failover tuttavia non e' semplicissima
e va eseguita con una certa attenzione...
Dalla versione 5.6 sono stati introdotti i
Global Transaction Identifier (GTID) che semplificano
notevolmente il failover ed in generale la gestione della replica MySQL.
L'aggancio di uno Slave avviene infatti con il semplice comando:
change master to master_auto_position=1.
Questa pagina riporta gli elementi principali sulla configurazione
e gestione della replica MySQL con GTID.
Nel seguito sono riportate alcune informazioni di interesse organizzate in paragrafi specifici: Introduzione, Configurazione, Architettura, Amministrazione, ...
Un'introduzione generale sulla replica in MySQL si trova su questo documento.
Storicamente la replicazione su MySQL e' basata sugli statement, asincrona e
l'identificazione degli statement e' file position based.
Il Master si occupa di registrare su file (bin-log file)
tutti gli statement che vengono eseguiti sulla base dati
e che operano una qualche modifica ai dati (DML e DDL).
Le istruzioni registrate sono identificate mediante la loro posizione nei file bin-log.
Lo Slave si collega con un thread al Master, raccoglie
il contenuto dei bin-log, lo trasferisce in locale e quindi
si occupa di applicarlo alla base dati.
Ogni versione di MySQL ha introdotto nuove funzionalita'
e dalla versione 5.6.5 sono stati introdotti i
Global Transaction Identifier (GTID).
Un GTID e' composto da source_id:transaction_id dove
il source_id e' l'identificativo del server che ha originato la
transazione mentre il transaction_id e' il numero progressivo
della transazione.
Utilizzando la replica basata su GTID non e' piu' necessario indicare file
e posizione delle istruzioni
da cui riallienare gli slave poiche' questo avviene in automatico.
Questo semplifica notevolmente le operazioni di failover (nel caso di crash del master),
di switchover (nel caso di modifica della topologia di replica) e di sincronizzazione
degli slave...
In pratica i principali vantaggi della replica GTID sono due:
Questo documento fa riferimento alla versione MySQL 5.7.6 o successiva poiche' da tale versione sono state consolidate tutte le funzionalita' introdotte in precedenza sul GTID.
La configurazione della replica con GTID e' simile a quella della replica file-based. La documentazione completa e' presente nel sito ufficiale, quindi nel seguito riportiamo un semplice esempio di configurazione... ma che copre tutti i punti fondamentali per l'avvio di una nuova replica direttamente con GTID!
Attivita' sul Master | Attivita' sullo Slave | Note |
[mysqld]
server-id=10 log-bin=mysql-bin enforce-gtid-consistency=ON gtid-mode=ON |
[mysqld]
server-id=20 read_only=ON enforce-gtid-consistency=ON gtid-mode=ON | La configurazione di base per la replica del Master e' semplice:
basta definire un server-id univoco ed indicare
il nome dei file di log binario.
Anche la configurazione dello Slave e' semplice: server-id univoco e parametro read_only. Altri parametri utili sono riportati nel seguito. |
grant replication slave on *.* to 'repl'@'%' identified by 'xyz'; | Non e' obbligatorio definire un nuovo utente ma e' consigliato sia per sicurezza che per semplicita' di configurazione e controllo | |
mysqladmin -p shutdown | mysqladmin -p shutdown | Bocce ferme |
service mysql start | service mysql start | Partiamo! |
reset master; | Si, sullo slave!
Serve solo se lo slave non e' "pulito", va eseguito prima del restore per permettere di impostare i gtid_purged. | |
Backup | Restore | Le modalita' backup/restore sono molteplici e dipendono da diversi fattori.
Con un normale backup effettuato con: mysqldump --all-databases --triggers --routines --events --single-transaction ... ed il normale restore, vengono automaticamente impostati sul gtid_purged dello Slave i gtid_executed del Master |
change master to master_host='myMaster.MyDomain.it', master_user='repl', master_port=3306, master_password='xyz', master_auto_position=1; | Con questo comando lo Slave sa come connettersi al Master e determina automaticamente da dove partire. | |
start slave; | Per far partire i thread dello Slave. Sono utilizzati un thread remoto (sul Master per inviare i bin-log) e due thread locali (per ricevere il bin-log ed applicarlo). | |
show slave status\G | Gia' fatto! Non c'e' altro da configurare sullo slave si controlla lo stato della replica GTID. |
I passi riportati e le spiegazioni sono un po' semplificati e ridondanti ma... rendono l'idea e funzionano per i casi principali (almeno spero ;-) E' ovvio che per far leggere i nuovi parametri del my.cnf e' necessario riavviare il server, che per lanciare uno statement SQL e' necessario collegarsi alla base dati, ...
Potrebbe essere necessario effettuare la conversione da una replica file-based ad una replica con GTID. I passi sono differenti perche' le basi dati sono gia' allineate. Ci sono diverse alternative, vediamo la piu' semplice!
Attivita' sul Master | Attivita' sullo Slave | Note |
SET @@global.read_only=ON; | Con questo comando si e' certi che sul master non avvengono modifiche. | |
mysqladmin -p shutdown | mysqladmin -p shutdown | Bocce ferme |
[mysqld]
enforce-gtid-consistency=ON gtid-mode=ON |
[mysqld]
enforce-gtid-consistency=ON gtid-mode=ON skip-slave-start | Impostiamo i parametri relativi alla replica GTID nei file my.cnf.
Lo slave non e' ancora agganciato al Master e per questo va disattivato all'avvio: e' molto importante se si parte da una condizione di replica file-based. |
service mysql start | service mysql start | Partiamo! |
change master to master_host='myMaster.MyDomain.it', master_user='repl', master_port=3306, master_password='xyz', master_auto_position=1; | Con questo comando lo Slave sa come connettersi al Master e determina automaticamente da dove partire. | |
start slave; | Per far partire i thread dello Slave. Sono utilizzati un thread remoto (sul Master per inviare i bin-log) e due thread locali (per ricevere il bin-log ed applicarlo). | |
SET @@global.read_only = OFF; | show slave status\G | Gia' fatto! Il Master puo' essere riabilitato in scrittura e possono ripartire le applicazioni.
|
[mysqld]
# skip-slave-start | Non dimentichiamo di eliminare la direttiva sulla configurazione dello slave! |
I passi riportati e le spiegazioni sono un po' semplificati ma... rendono l'idea (almeno spero ;-)
Nel caso non sia possibile effettuare il riavvio dei DB
e' utilizzabile una procedura per effettuare l'attivazione online del GTID.
In pratica i passi da eseguire su ogni server presente
e da verificare prima di passare alla fase sucessiva sono:
SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN; -- Controllare eventuali errori nel log SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = ON; SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE; SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE; -- SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT' deve andare a 0 FLUSH LOGS SET @@GLOBAL.GTID_MODE = ON; -- Da impostare anche nel my.cnf con gtid-mode=ONQuindi su ogni slave:
STOP SLAVE; CHANGE MASTER TO MASTER_AUTO_POSITION = 1; START SLAVE;
Come gia' indicato... non dimenticare di impostare i parametri corretti anche nel file my.cnf.
La procedura indicata e' disponibile dalla versione 5.7.6, la documentazione ufficiale riporta tutti i dettagli.
La configurazione vista nel paragrafo precedente e' gia' perfettamente funzionante.
Ulteriori parametri relativi alla replica in generale
sono riportati in questo documento.
In questo breve capitolo descriviamo in modo compiuto
i parametri relativi alla replicazione GTID.
Il parametro enforce-gtid-consistency puo' assumere
i valori ON, OFF e WARN e va impostato ad ON per attivare la replica GTID.
gtid-mode assume i valori ON, OFF, OFF_PERMISSIVE, ON_PERMISSIVE
gtid-executed-compression-period che viene utilizzato per effettuare
la compressione periodica della tabella mysql.gtid_executed
se log_bin e' impostato ad OFF.
I parametri di configurazione utilizzabili, come abbiamo visto, sono molteplici... Per riassumere riportiamo una possibile configurazione finale che contiene tutti i parametri di interesse per la replica (compresi quelli che hanno un impatto sulle prestazioni). La configurazione e' relativa ad una semplice architettura in cui sono presenti un master ed uno slave configurati in replicazione GTID:
Parametri consigliati per la replica GTID |
[mysqld]
server-id=N log-bin=mysql-bin relay_log=mysql-relay-bin relay_log_index=mysql-relay-bin.index enforce-gtid-consistency=ON gtid-mode=ON innodb_flush_log_at_trx_commit=1 sync_binlog=1 relay_log_info_repository=table master_info_repository=table report-host=Hostname report-port=3306 expire_logs_days=8 slave-parallel-workers=4 slave-parallel-type=LOGICAL_CLOCK slave_preserve_commit_order=1 # read_only=ON ### Su tutti gli slave # super_read_only=ON ### Su tutti gli slave |
Alcuni parametri sono specifici per Master/Slave, altri sono relativi alle performances, ... ma e' opportuno che le configurazioni siano allineate tra loro per disporre delle stesse performance in caso di switchover.
Anche se molto potente, la replicazione di MySQL ha alcuni limiti che non consentono di replicare tutto in tutti i casi... Le limitazioni della replica in generale sono descritte in questo documento e sul sito ufficiale.
Inoltre vi sono ulteriori limitazioni relative alla replica GTID dovute alla necessita' di serializzare le transazioni. Per evitare che la replica GTID si blocchi viene utilizzato il parametro enforce-gtid-consistency che fa fallire sul Master gli statement problematici.
Tra gli statement non corretti all'interno di una transazione per la replica GTID:
Una errant transaction e' una transazione eseguita direttamente su uno slave anziche' sul master. Le errant transaction sono sempre esistite ma con la replica GTID generano problemi in caso di failover. Infatti viene mantenuta la lista dei GTID eseguiti ed il protocollo prevede lo scambio e l'esecuzione delle transazioni mancanti: durante il failover possono cosi' essere eseguite transazioni mai eseguite sul Master che possono bloccare la replica o, molto peggio, corrompere i dati senza alcun preavviso o segnalazione.
La prima cura contro le errant transaction e' la prevenzione: impostare in read_only gli Slave e tagliare le mani o i GRANT agli utenti troppo volenterosi [NdE super_read_only dalla 5.7.8] !!!
Per verificare la presenza di errant transaction si deve confrontare l'elenco dei GTID eseguiti sul Master e sugli Slave. I GTID eseguiti sugli Slave debbono essere un sottoinsieme di quelli eseguiti sul Master.
Quando le analisi sulle errant transaction danno risultato positivo e' necessario
curarle subito con un'iniezione... e non e' una battuta!
E' necessario evitare che una errant transaction venga eseguita
quando lo Slave su cui si e' operato diventa un Master.
Per evitarlo si utilizza la tecnica di inserire una transazione con lo stesso GTID
ma vuota sul master (che la replica sugli altri slave) o singolarmente
sugli slave (se il master non c'e' piu'):
Questa tecnica (Empty Transaction Injection) e' utilizzabile anche per far "saltare" transazioni
che danno errore su uno Slave.
Infatti il parametro sql_slave_skip_counter non e' utilizzabile con il GTID.
Nel caso in cui le transazioni siano molte e si debba eseguire l'operazione su piu' slave
si puo' lanciare un comando delle utility:
mysqlslavetrx --gtid-set=dad..:9-69 --slaves=adm_repl:XXX@slave2:3312,adm_repl:XXX@slave3:3313
Per eliminare le errant transaction l'altra possibilita' e' quella di rimuovere i GTID indesiderati, ma e' un operativa che richiede piu' tempo: quindi non la descrivo. In ogni caso e' poi opportuna una verifica sulla consistenza dei dati.
L'amministrazione di una replica con GTID e' analoga all'amministrazione della replica file-based ma alcune procedure sono semplificate.
Nell'operazione di switchover si vuole promuovere uno Slave (S2) a Master.
S2 SQL> STOP SLAVE IO_THREAD; M1 SQL> CHANGE MASTER TO <new_master_def>; M1 SQL> START SLAVE; S1 SQL> STOP SLAVE IO_THREAD; S1 SQL> CHANGE MASTER TO <new_master_def>; S1 SQL> START SLAVE IO_THREAD;
La nuova configurazione e' immediatamente disponibile. Vanno solo reimpostati gli eventuali parametri READ_ONLY.
Qualche altro esempio? Nei due esempi seguenti viene resa evidente la semplificazione apportata con i GTID che non richiede la ricerca della posizione precisa del binlog ma la ricava in automatico. Aggiunta di un nuovo Slave:
Ripristino di un nuovo Slave che ha "perso la strada" (molto piu' semplice rispetto a quella della normale replica):
Un ulteriore vantaggio della replica GTID e' quello che e' possibile utilizzare routine che effettuano in automatico tutte le operazioni necessarie su tutti gli slave e tenendo conto di tutte le condizioni (eg. Errant Transactions): continuate a leggere!
MySQL distribuisce una serie di utility tra cui mysqlfailover e mysqlrpladmin che sono utili per la gestione della replica GTID [NdA arch. link].
Lo script mysqlfailover opera su una configurazione anche complessa di replica con GTID effettuando in automatico le operazioni di failover o di switchover.
# Configurazione utente grant all on *.* to adm_repl@'%' identified by 'XXX'; grant SUPER, GRANT OPTION, REPLICATION SLAVE, SELECT, RELOAD, DROP, CREATE, INSERT on *.* to adm_repl@'%' ; # Visualizzazione la console mysqlfailover -f auto --force --master=adm_repl:XXX@10.1.2.13:3306 --slaves=adm_repl:XXX@10.1.2.17:3306 --candidates=adm_repl:XXX@10.1.2.17:3306
L'utilizzo piu' comune di mysqlfailover e' pero' con l'opzione --daemon
che lo pone in background in attesa di un evento su cui intervenire.
In molti casi e' necessario lanciare script (eg. riconfigurazione delle connessioni,
attivazione VIP): questo e' possibile con i parametri exec-after, exec-before, ...
Per la normale amministrazione tipicamente si utilizza
lo script mysqlrpladmin opera manualmente
su una configurazione anche complessa di replica con GTID
effettuando le operazioni di failover o di switchover occupandosi
di lanciare tutti i comandi necessari su
tutti i nodi coinvolti.
Le opzioni dei due comandi sono analoghe.
La
replica GTID implementata su MariaDB
non e' compatibile con quella MySQL
quindi non possono essere posti in replica GTID DB con MySQL e MariaDB.
La replica GTID e' compatibile con Galera Cluster, anzi presenta alcuni
ulteriori vantaggi rispetto alla replica classica.
Titolo: MySQL GTID Replication
Livello: Avanzato
Data:
1 Aprile 2015
Versione: 1.0.3 - 14 Febbraio 2016 ❤️ San Valentino
Autore: mail [AT] meo.bogliolo.name