Backup automatico di MySQL con rotazione e verifica
Come creare un sistema semplice e affidabile per eseguire backup automatici di MySQL, conservarne più versioni, verificarne l'integrità e testare periodicamente il ripristino.
Un backup utile non è semplicemente un file SQL lasciato in una directory. Un sistema di backup affidabile deve produrre copie coerenti, conservarne più versioni, verificare che i file siano leggibili e, soprattutto, permettere di dimostrare che un ripristino è realmente possibile. Per un server MySQL di piccole o medie dimensioni, una soluzione semplice basata su mysqldump, cron, compressione, rotazione e test di integrità può offrire un buon punto di partenza senza introdurre infrastrutture complesse.
Quale strategia scegliere
MySQL distingue tra backup logici e fisici. Un backup logico interroga il server e produce istruzioni SQL che possono ricreare struttura e dati; è portabile e può essere ripristinato anche su un ambiente differente. mysqldump è lo strumento tradizionale per questo tipo di backup. Per database molto grandi, invece, un backup fisico può essere più rapido da ripristinare, ma richiede strumenti e procedure differenti.
In questo articolo costruiamo una procedura orientata soprattutto a MySQL 8.4 e a tabelle InnoDB. L'obiettivo è avere un backup giornaliero automatico, mantenere per esempio gli ultimi quattordici giorni, comprimere i dump e verificare automaticamente che il file prodotto sia integro. La procedura non sostituisce una strategia completa di disaster recovery: una copia locale non protegge da guasti del server, furto, ransomware o cancellazione accidentale dell'intera macchina.
Preparare una directory dedicata
È buona pratica separare i backup dai dati del database. Ad esempio:
sudo install -d -m 750 -o root -g backup /var/backups/mysql
Se il sistema non dispone del gruppo backup, è possibile usare un gruppo dedicato oppure una directory accessibile soltanto all'utente che esegue il job. L'importante è evitare permessi aperti: i dump possono contenere password hashate, dati personali e informazioni applicative riservate.
Creare un account MySQL dedicato
Il job di backup non dovrebbe utilizzare l'account amministrativo principale. Creiamo invece un account con i privilegi necessari al dump. I privilegi esatti dipendono dalla versione, dalle opzioni utilizzate e dagli oggetti presenti nel database; per un ambiente reale è quindi opportuno verificare i requisiti della propria versione di MySQL prima di restringere ulteriormente i permessi.
CREATE USER 'backup'@'localhost' IDENTIFIED BY 'PASSWORD-MOLTO-LUNGA';
GRANT SELECT, SHOW VIEW, TRIGGER, EVENT
ON *.* TO 'backup'@'localhost';
FLUSH PRIVILEGES;
Non inserire la password direttamente nello script. È preferibile utilizzare un file di opzioni leggibile soltanto dall'utente che esegue il backup. Ad esempio:
sudo install -m 600 -o root -g root /dev/null /root/.my.cnf
e poi:
[client]
user=backup
password=PASSWORD-MOLTO-LUNGA
host=localhost
In ambienti più sensibili si può valutare una gestione delle credenziali ancora più strutturata. Il principio fondamentale è comunque non lasciare password nel comando mostrato da ps, nella cronologia della shell o nei file accessibili ad altri utenti.
Il comando mysqldump
Per database InnoDB, --single-transaction consente di ottenere un dump consistente senza bloccare normalmente le tabelle per tutta la durata dell'operazione. È una scelta adatta ai database transazionali, ma non deve essere interpretata come una garanzia universale: tabelle non transazionali e operazioni DDL possono richiedere attenzione specifica.
Una base di comando può essere:
mysqldump --all-databases --single-transaction --routines --events --triggers --hex-blob --set-gtid-purged=AUTO > /var/backups/mysql/full.sql
Le opzioni --routines, --events e --triggers sono importanti quando l'applicazione utilizza oggetti oltre a tabelle e viste. La configurazione reale va comunque adattata alle caratteristiche del server.
Comprimere il dump
Un dump SQL può essere molto più grande dei dati effettivi. La compressione riduce spazio e tempi di trasferimento. Una soluzione semplice è usare gzip:
mysqldump --all-databases --single-transaction --routines --events --triggers | gzip -c > /var/backups/mysql/mysql-$(date +%F_%H-%M-%S).sql.gz
È preferibile scrivere prima in un file temporaneo e rinominarlo soltanto dopo il completamento. In questo modo un processo interrotto non lascia un file apparentemente valido con un nome definitivo.
Uno script completo
Un approccio pratico è creare /usr/local/sbin/mysql-backup.sh:
#!/bin/bash
set -Eeuo pipefail
BACKUP_DIR="/var/backups/mysql"
RETENTION_DAYS=14
STAMP="$(date +%F_%H-%M-%S)"
FINAL="$BACKUP_DIR/mysql-$STAMP.sql.gz"
TMP="$FINAL.tmp"
mkdir -p "$BACKUP_DIR"
mysqldump --all-databases --single-transaction --routines --events --triggers --hex-blob --set-gtid-purged=AUTO | gzip -c > "$TMP"
test -s "$TMP"
gzip -t "$TMP"
mv "$TMP" "$FINAL"
find "$BACKUP_DIR" -type f -name 'mysql-*.sql.gz' -mtime +"$RETENTION_DAYS" -delete
echo "Backup completato: $FINAL"
Rendiamo eseguibile lo script:
sudo chmod 750 /usr/local/sbin/mysql-backup.sh
Qui ci sono già due controlli importanti: test -s verifica che il file non sia vuoto e gzip -t verifica la struttura del file compresso. Sono controlli di integrità, non un vero test di ripristino.
Gestire la rotazione
La rotazione impedisce che i backup consumino indefinitamente lo spazio disponibile. Nel nostro esempio conserviamo quattordici giorni. Prima di applicare una politica automatica, però, è necessario considerare il valore dei dati, la frequenza dei backup e il tempo massimo entro cui si deve poter tornare indietro.
La retention deve inoltre essere coordinata con eventuali binary log. MySQL 8.4 abilita normalmente il binary logging e ha una scadenza automatica predefinita di trenta giorni, ma il periodo effettivo deve essere scelto in funzione delle esigenze di recupero e, in presenza di repliche, del massimo ritardo previsto. Eliminare i binary log troppo presto può compromettere un recupero point-in-time.
Programmare il backup con cron
Per un server Linux semplice possiamo usare cron. Ad esempio:
sudo crontab -e
Per eseguire il backup ogni notte alle 02:15:
15 2 * * * /usr/local/sbin/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1
La scelta dell'orario deve evitare, quando possibile, i periodi di maggiore carico. Il log deve essere monitorato: un cron che fallisce in silenzio non è un sistema di backup affidabile.
Verificare che il backup sia davvero ripristinabile
La verifica più importante è il restore. Un file che passa gzip -t può essere perfettamente integro dal punto di vista della compressione e tuttavia contenere un dump inutilizzabile per l'applicazione. La procedura migliore consiste nel ripristinare periodicamente una copia su un'istanza MySQL separata.
Per un test di base, su un ambiente dedicato e non sul database di produzione:
gunzip -c /var/backups/mysql/mysql-2026-09-22_02-15-00.sql.gz | mysql
Dopo il restore è opportuno controllare che i database attesi esistano, che le tabelle siano presenti e che l'applicazione riesca a eseguire le operazioni principali. Il test deve essere automatizzato almeno in parte e registrato, così da poter dimostrare quando è stato eseguito l'ultimo ripristino riuscito.
Aggiungere una copia fuori dal server
La rotazione locale non protegge dal guasto del disco che contiene sia il database sia i backup. Per questo è necessario copiare periodicamente i file verso un secondo sistema: NAS, altro server, object storage o altro repository controllato. Una regola pratica è mantenere almeno una copia su un sistema separato e, per dati importanti, una copia che non possa essere modificata o cancellata insieme al server di produzione.
Prima di cancellare i backup locali è necessario assicurarsi che la copia remota sia stata completata e verificata. Il semplice comando di copia non costituisce una garanzia di successo.
Checksum e verifica remota
Un checksum può aiutare a verificare che il file trasferito sia identico all'originale. Per esempio:
sha256sum /var/backups/mysql/mysql-2026-09-22_02-15-00.sql.gz > /var/backups/mysql/mysql-2026-09-22_02-15-00.sha256
Il checksum non sostituisce il restore test: dimostra che i byte sono gli stessi, non che il contenuto rappresenti una copia corretta e utile del database.
Quando entra in gioco il binary log
Se è necessario recuperare il database fino a un momento specifico, il solo dump giornaliero può non essere sufficiente. Il binary log registra le modifiche successive al backup e può essere utilizzato con mysqlbinlog per un recupero point-in-time. La strategia tipica prevede un backup completo e la conservazione dei binary log necessari fino al momento desiderato.
Prima di applicare politiche di purge, è fondamentale verificare quali log servono ancora. In particolare, un server che alimenta repliche non deve cancellare log prima che le repliche li abbiano elaborati.
Errori comuni da evitare
- Un solo backup locale: protegge da alcuni errori logici, ma non dal guasto del server.
- Nessun test di restore: è il problema più grave, perché l'errore viene scoperto solo durante l'emergenza.
- Password nello script: aumenta il rischio di esposizione delle credenziali.
- Retention infinita: può riempire il disco fino a bloccare il database.
- Cancellazione aggressiva dei binary log: può ridurre la possibilità di recupero o interferire con la replica.
- Backup durante carichi non controllati: può aumentare tempi e impatto sul server.
- Nessun monitoraggio: un job automatico deve generare segnali quando fallisce.
Una politica semplice ma efficace
Per un piccolo server MySQL, una politica ragionevole può essere un backup completo giornaliero, quattordici giorni di retention locale, una copia separata su un secondo sistema e un restore test mensile. Se il database è critico, è opportuno aggiungere binary log e una procedura point-in-time recovery, oltre a una retention più articolata.
La parte più importante non è il comando mysqldump in sé, ma l'intera catena: generazione, protezione, rotazione, copia fuori dal server, monitoraggio e ripristino. Un backup che non è mai stato ripristinato è soltanto una speranza.
Conclusione
Con pochi strumenti disponibili su Linux è possibile costruire un sistema di backup MySQL automatico, leggibile e relativamente semplice da mantenere. mysqldump è particolarmente adatto ai backup logici di database di dimensioni moderate, mentre la compressione riduce lo spazio occupato e una politica di retention evita la crescita incontrollata. La verifica del file e, soprattutto, i test periodici di restore trasformano una semplice copia in una procedura di recupero.
Quando i dati crescono o i requisiti di disponibilità diventano più stringenti, è il momento di valutare strumenti di backup fisico, replica, object storage, snapshot e procedure di disaster recovery più avanzate. Ma anche in questi scenari i principi restano gli stessi: sapere che cosa viene salvato, dove si trova, per quanto tempo viene conservato e quanto tempo serve per ripristinarlo.
Share
What's Your Reaction?
Like
0
Cancella like
0
Amore
0
Buffo
0
arrabbiato
0
Sad
0
Wow
0