MySQL over ZFS tutorial

ZFS è un filesystem, originariamente sviluppato per Solaris e successivamente integrato in FreeBSD, con interessanti funzionalità tra le quali, la gestione del raid via sofware, la compressione dei files, creazione efficente degli snapshot (grazie ad un meccanismo di copy-on-write), cloni, etc.

In questo articolo vedremo come installare MySQL su un sistema FreeBSD con filesystem ZFS e come sfruttarne gli snapshot per effettuare dei backup binari del database in maniera efficiente e senza mai mettere offline il database (faremo cioè un hotbackup).

Tecniche di backup su MySQL

Senza dilungarsi troppo sull'argomento, possiamo dire che esistono principalmente due tipologie di backup di un database MySQL:

  • backup logici (generazione di file SQL tramite comando mysqldump, export in file CSV, copia tramite replication/binlog)
  • backup fisico (copia dei file contenenti dati e metadati)

Quale sia il meccanismo "migliore" dipende da diversi fattori come: dimensioni del database, possibilità o meno di mettere il database offline per un certo tempo ,disponibilità di hardware, etc

Vediamo adesso come sfruttare ZFS per effettuare un hotbackup. Quello che dovremo fare è:

  • "mettere in pausa", per il più breve tempo possibile, le attività sul database; questo NON significa arrestare MySQL e neanche fermare i vari client che si collegano ad esso; quello di cui abbiamo bisogno sono pochi istanti in cui il database sia coerente. Otterremo questa pausa tramite il comando FLUSH TABLES WITH READ LOCK.
  • effettuare la copia dei files tramite snapshot zfs.

prima di poter procedere abbiamo bisogno di un ambiente adeguatamente configurato.

Setup dall'ambiente

Dopo aver installato FreeBSD sul vostro server sarà necessario:

  • abilitare ZFS, inserendo la riga zfs_enable="YES" nel file /etc/rc.conf
  • creare un pool zfs e montarlo (ad esempio nella directory /storage - negli esempi supponiamo di avere installato freebsd sul disco ada0 e di avere due dischi uguali ada1 ed ada2 che si vogliono tenere in mirroring). Eseguire il comando: zpool create -m /storage storage mirror ada1 ada2
  • adesso il filesystem zfs è pronto!

Installiamo MySQL tramite i comandi:

cd /usr/ports/database/mysql55
make
make install
make clean
cp /usr/local/share/mysql/my-medium.cnf /usr/local/etc/my.cnf

echo 'mysql_enable="YES"' >> /etc/rc.conf

Configuriamo MySQL in modo che usi come directory di lavoro la cartella /storage (quella creata poco prima con zfs). Per farlo è necessario inserire una riga mysql_dbdir="/storage" nel file /etc/rc.conf

Facciamo partire MySQL tramite /usr/local/etc/rc.d/mysql-server start

Complimenti! Adesso avete un database funzionante su zfs.

Esecuzione del backup

Adesso non resta che fare, tanti, frequenti backup. Per effettuarli basta eseguire i seguenti passi:

  1. collegarsi a mysql, ad esempio tramite mysql -u root -punapassword
  2. acquisire un lock globale su tutte le tabelle tramite il comando sql FLUSH TABLES WITH READ LOCK;
  3. in una diversa console, creare uno snapshot tramite il comando di shell zfs snapshot storage@snapshot1 (in generale storage@NomeDelloSnapshot)
  4. rilasciare il lock globale con il comando sql UNLOCK TABLES;

La creazione dello snapshot al punto (3) durerà soltanto una manciata di secondi, il che è accettabile nella maggioranza delle situazioni reali (ad es. facendo un test su una macchina virtuale sul mio portatile con un database di prova di circa 2GB la creazione dello snapshot dura circa 1.5 secondi).

Lo snapshot già così è un backup, ma è sulla stessa macchina del database. Il buon senso prevede che i backup non si tengano sullo stesso server da backuppare, quindi potremmo:

(a) salvarlo su un file e poi masterizzarlo: zfs send storage@snapshot1 > mysql.backup

oppure

(b) inviare il backup ad un altro host: zfs send storage@snapshot1 | ssh host zfs recv storage@snapshot1

Queste operazioni potrebbero occupare del tempo (dipende dalle dimensioni del backup), ma nel frattempo mysql continuerà a lavorare senza provocare disservizio alcuno.

Una nota importante: gli snapshot non sono gratis... potrebbero occupare spazio su disco (tanto o poco, dipende dall'utilizzo del sistema) e la scrittura sulle porzioni di disco coinvolte in snapshot è più lenta a causa del meccanismo del copy-on-write. Quindi: quando non vi servono più... cancellateli!

L'elenco degli snapshot è visualizzabile tramite:

zfs list -t snapshot

per cancellarne uno utilizzare:

zfs destroy filesystem@nomeSnapshot

(es. zfs destroy storage@snapshot1)


Ripristino di un backup

Se abbiamo inviato uno snapshot al file mysql.backup (vedi zfs send) possiamo effettuare il restore tramite:

zfs recv /storage < mysql.backup


Performance

Per ottenere delle buone performance con MySQL/ZFS si consiglia di:

  • disabilitare il prefetch di zfs (aggiungendo una riga vfs.zfs.prefetch_disable=1 nel file /etc/sysctl.conf)
  • disabilitare il doppio buffering di InnoDB (aggiungendo la riga skip-innodb_doublewrite nel file my.cnf)
  • limitare la memoria ram utilizzata da zfs per lasciarne una quantità maggiore a MySQL (aggiungendo una riga vfs.zfs.arc_max=num_bytes nel file /etc/sysctl.conf)
  • impostare il record size del filesystem in modo da farlo corrispondere a quello di innodb (eseguendo, nel nostro esempio, zfs set recordsize=16k storage)

Nel caso in cui si disponga di un hard disk a stato solido (SSD)  è possibile utilizzarlo come cache. Se supponiamo che l'SSD sia il device da0 eseguire:

zpool add storage cache da0

Volendo, è anche possibile utilizzare un disco dedicato per l'intent log di zfs eseguendo: zpool add storage log da1

 

Conclusioni

Con questo articolo abbiamo visto soltanto alcune delle carattestiche di ZFS e di come possano essere utili nella gestione di un database MySQL (ma non solo!). Spero di avervi stimolato l'appetito riguardo a questa tecnologia ;-)

 

Maggiori informazioni su ZFS

Per non appesantire troppo l'articolo, abbiamo utilizzato un pool zfs soltanto per gestire i dati di MySQL ma è possibile configurare il sistema in modo che sia interamente su ZFS: maggiori informazioni in tal senso le trovate nel seguente articolo:

Per uno studio più approfondito di ZFS, la documentazione ufficiale di FreeBSD è un'ottima fonte:

MySQL+ZFS Best pratices by Oracle:

Altro link interessante (anche se relativo a Solaris):

Il backup che abbiamo visto in questo articolo è un backup "completo" del database. Per database di dimensioni "esagerate" probabilmente è meglio effettuare degli snapshot incrementali. Maggiori informazioni qui:

Come configurare una replication usando ZFS:

Si può fare qualcosa di simile su Linux ?

Linux non supporta ZFS per problemi di licenza. Probabilmente si può comunque configurare un ambiente simile utilizzando BTRFS (non ho fatto test in merito). BTRFS è un filesystem disponibile sotto Linux che ha diverse caratteristiche simili a ZFS; tale filesystem però non è ancora considerato 'stabile' per cui se ne sconsiglia (al momento) l'utilizzo su sistemi di produzione.
Per maggiori informazioni consultare le seguenti pagine web: