Backup di un database MySQL tramite snapshot ZFS


12

Ho trovato numerosi siti che parlano esattamente di questo, ma mi mancano alcuni dettagli importanti. I passaggi generali sono

  • Correre FLUSH TABLES WITH READ LOCK
  • Scatta l'istantanea ZFS
  • Correre UNLOCK TABLES

Varie fonti riportano che InnoDB, che sto usando, in realtà non onora un FLUSH. Il manuale dell'utente di MySQL indica che esiste una FLUSH TABLES...FOR EXPORTvariante per l'utilizzo con InnoDB, ma che richiede di specificare ciascuna tabella singolarmente, anziché eseguire il backup dell'intero database. Preferirei evitare di specificare ogni tabella singolarmente perché esiste una buona possibilità che l'elenco delle tabelle diventi non sincronizzato con le tabelle che esistono effettivamente.

L'altro problema che ho è che ho pianificato di fare qualcosa del genere mysql -h"$HOST" -u"$USERNAME" -p"$PASSWORD" --execute="FLUSH TABLES WITH READ LOCK". Tuttavia, questo rilascia il blocco immediatamente dopo la chiusura della sessione. Questo ha senso, ma è anche piuttosto fastidioso poiché devo tenere il blocco di lettura quando scatto la mia istantanea.

L'altra mia idea è quella di fare un backup a caldo usando uno strumento come Percona XtraBackup e scattare istantanee del backup, ma preferirei non pagare il costo per scrivere tutti i miei dati in una seconda posizione solo per fare un'istantanea.


Perché un elenco statico di tabelle? Puoi sicuramente generare un elenco in modo dinamico in fase di esecuzione.
EEAA,

1
Il database è su una macchina virtuale o su bare metal? L'archiviazione è anche sulla stessa macchina?
Michael Hampton

EEAA, abbastanza giusto.
Andy Shulman,

Michael, il database e la scatola ZFS sono macchine diverse, ma nessuna delle due è virtualizzata.
Andy Shulman,

@AndyShulman Penso che dovresti spiegare un po 'meglio il layout. Questo non ha senso.
ewwhite,

Risposte:


4

Se usi InnoDB solo per tutte le tabelle e imposti innodb_flush_log_at_trx_commitsu:

  • 1 (il contenuto del buffer di registro InnoDB viene scritto nel file di registro ad ogni commit della transazione e il file di registro viene scaricato sul disco) o,
  • 2 (il contenuto del buffer di registro InnoDB viene scritto nel file di registro dopo ogni commit della transazione e il file di registro viene scaricato sul disco circa una volta al secondo),

quindi non hai bisogno di FLUSH TABLES prima di fare un'istantanea, esegui direttamente l'istantanea ZFS. InnoDB può recuperare i dati dai registri di commit delle transazioni senza perdita di dati.

Rif: https://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit


Con il dizionario dei dati introdotto in MySQL 8, anche le operazioni DDL (modifica dello schema) sono ora atomiche. Prima di ciò, le operazioni DDL durante un'istantanea del filesystem potevano dare risultati parzialmente impegnati (cioè corrotti).
Bernie,

13

È necessario un blocco completo del database per eseguire il backup di uno (più) database in modo coerente.

Il manuale https://dev.mysql.com/doc/refman/5.5/en/backup-methods.html afferma che FLUSH TABLES WITH READ LOCK è specifico per le istantanee ZFS.

Esecuzione di backup mediante un'istantanea del file system

Se si utilizza un file system Veritas, è possibile eseguire un backup in questo modo:

  1. Da un programma client, eseguire FLUSH TABLES WITH READ LOCK.
  2. Da un'altra shell, eseguire mount vxfssnapshot.
  3. Dal primo client, eseguire UNLOCK TABLES.
  4. Copia i file dall'istantanea.
  5. Smonta l'istantanea.

Funzionalità di istantanee simili potrebbero essere disponibili in altri file system, come LVM o ZFS.

E 'sorta di ridicolo che hanno lasciato fuori il fatto che è necessario FLUSH TABLES table_a, table_b, table_c FOR EXPORTper InnoDB da queste istruzioni. È anche stupido dover specificare ogni tabella in questo modo. Ma, come afferma EEAA, è possibile generare un elenco di tabelle quando si avvia il backup abbastanza facilmente.

Per quanto riguarda il mantenimento del blocco, è necessario mantenere attiva la connessione db durante l'esecuzione dell'istantanea

Generalmente userei qualcosa come Perl o un altro linguaggio di programmazione che può connettersi, bloccare il db e mantenendo la connessione db prendere l'istantanea, quindi sbloccare e disconnettermi. Non è complesso Scommetto che ci sono strumenti là fuori che lo fanno già, ma scriverne uno è facile.

Dico facile, non complesso, ecc. Alcune volte. Suppongo che tu abbia una programmazione di base o buone capacità di scripting.


Avevo sperato di mantenere uno script concettualmente semplice in Bash, ma hai ragione a cambiare lingua rende tutto molto più semplice. Potrei leggere la tua risposta in modo sbagliato, ma sembra che tu stia dicendo che devo eseguire entrambi FLUSH TABLES WITH READ LOCKe poi FLUSH TABLES...FOR EXPORT, mentre la mia lettura del manuale di MySQL dice che dovrebbe essere necessario solo uno.
Andy Shulman,

Mi dispiace non sono stato chiaro. Sto solo seguendo il manuale e dice due cose diverse. Immagino che tu abbia ragione e che abbia bisogno solo del dopo. Ma tutte le tabelle dovrebbero essere bloccate in un solo comando.
Ryan Babchishin,

1
Dato che la documentazione non è molto chiara, l'intero database deve essere bloccato e che una connessione DB deve essere mantenuta mentre viene eseguita l'istantanea, sembra più semplice semplicemente chiudere il database, eseguirne il backup e riavviare esso.
Andrew Henle,

2
@andrew sospiro ... ho capito. Ma questo sarà lento, causerà la caduta / interruzione delle connessioni e ho visto che i database non riescono a tornare correttamente (male per l'automazione). Sarebbe bene ottenere una risposta definitiva da mysql / Oracle. Devono avere una mailing list.
Ryan Babchishin,

7

Ho strappato e adattato una sceneggiatura concettualmente semplice in Bash che ho trovato in un altro post di Server Fault di Tobia . Dovrebbe arrivare a circa il 90% del percorso lì.

mysql_locked=/var/run/mysql_locked

# flush & lock MySQL, touch mysql_locked, and wait until it is removed
mysql -hhost -uuser -ppassword -NB <<-EOF &
    flush tables with read lock;
    delimiter ;;
    system touch $mysql_locked
    system while test -e $mysql_locked; do sleep 1; done
    exit
EOF

# wait for the preceding command to touch mysql_locked
while ! test -e $mysql_locked; do sleep 1; done

# take a snapshot of the filesystem, while MySQL is being held locked
zfs snapshot zpool/$dataset@$(date +"%Y-%m-%d_%H:%M")

# unlock MySQL
rm -f $mysql_locked

Qui, il mysqlcomando che usi viene eseguito in background e tocca un file. Attende in background che il file scompaia prima di uscire e quindi sbloccare le tabelle. Nel frattempo lo script principale attende fino a quando il file esiste, quindi crea lo snapshot ed elimina il file.

Il file a cui punta $mysql_lockeddeve essere accessibile ad entrambi i computer, cosa che dovresti essere in grado di fare abbastanza facilmente poiché entrambi possono accedere a un set di dati comune (anche se potrebbero usare percorsi diversi, e dovresti tenerne conto).


Non conosco lo scripting MySQL, quindi questa potrebbe essere un'idea sciocca, ma non potresti semplicemente farlo system zfs snapshot...all'interno dello script principale? O lo snap-shotting deve essere eseguito in un processo separato?
TripeHound,

@Tripehound entrambe le cose devono accadere in parallelo in qualche modo
Ryan Babchishin,

@RyanBabchishin Penso che abbia ragione, in realtà. Il SYSTEMcomando esegue le cose localmente. Se avessi eseguito il client mysql sulla scatola di FreeBSD ed eseguito LOCK; SYSTEM zfs snapshot; UNLOCK, sembra che funzionerebbe.
Andy Shulman,

@Andy ho appena detto che devono accadere in parallelo. Non importa come lo fai.
Ryan Babchishin,

2

Per myisam hai bisogno di FLUSH TABLES WITH READ LOCK perché non è journaling.

Non hai davvero bisogno di nulla per innodb, IMO, perché è il journaling. Sarà comunque coerente, ripristina automaticamente il diario se succede qualcosa nell'istante atomico in cui scatti.

Se si desidera la coerenza a livello di applicazione, l'applicazione deve utilizzare le transazioni. Se la tua applicazione utilizza transazioni e innodb, qualsiasi snapshot sarà coerente e richiedi automaticamente il passaggio al livello dell'applicazione.


2

Questa è la mia soluzione su come creare uno snapshot ZFS mantenendo il blocco:

mysql << EOF
    FLUSH TABLES WITH READ LOCK;
    system zfs snapshot data/db@snapname
    UNLOCK TABLES;
EOF
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.