E' possibile far sė che MySQL tenga traccia di tutte le query di comando eseguite su ogni database. Accoppiando questa feature con un meccanismo di backup, č possibile ripristinare un database danneggiato per riportarlo al momento presente.
Innanzitutto si prevede di effettuare un backup periodico dei databases; questo può essere eseguito da cron, garantendo così il salvataggio dei dati almeno fino all'ultimo backup.
Quando viene installato di default, MySQL prevede di eseguire un log esclusivamente delle fasi di avvio e fermata, e di eventuali errori del server. In genere, questi log vengono salvati in /var/lib/mysql/mysqld.log
.
Una volta installato MySQL, si modifichi il file /etc/my.cnf
come segue:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-update=/var/log/mysql/queries
log-long-format
...
[mysql.server]
...
[safe_mysqld]
err-log=/var/log/mysql/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
...
Sono evidenziate nello script le parti da modificare. Come si vede, si è preferito far scrivere i log di MySQL su una cartella a parte, /var/log/mysql, un po' per analogia con altri server "importanti", come Samba o Apache, ma anche per il numero di logs che MySQL creerà, come vedremo tra poco.
Occorre ora creare la cartella e darle i permessi necessari:
mkdir /var/log/mysql
chown mysql:mysql /var/log/mysql
chmod 775 /var/log/mysql
Poichè abbiamo spostato la directory dei logs, dovremo cambiare anche il file che MySQL crea per la rotazione dei suoi log standard; la sua posizione dipende dalla distribuzione. Se MySQL è stato installato da pacchetti RPM, si troverà in /etc/logrotate.d/mysql
. Basterà cambiare la riga che indica la posizione del file di log, da
...
/var/lib/mysql/mysqld.log {
....
a
...
/var/log/mysql/mysqld.log {
....
(N.B. magari, se avete impostato una password per l'utente root di MySQL, modificate anche la riga più oltre che esegue lo scarico dei logs, inserendovi anche la password:
if test -n "`ps acx|grep mysqld`"; then
/usr/bin/mysqladmin --password=pwd_di_root
flush-logs
fi
)
Ora provate a lanciare il server MySQL (o a fermalo e riavviarlo, se già attivo) ed eseguire alcune query di comando (INSERT, DELETE, UPDATE...) sui databases. Nella cartella /var/log/mysql
si creerà un file queries.001
con un contenuto di questo genere:
# /usr/sbin/mysqld, Version: 4.0.15-standard-log at 040301 14:17:16
# Time: 040301 18:38:28
# User@Host: pippo[pippo] @ localhost []
USE dbProva;
UPDATE Download SET IDuser=149, Descrizione="Inserimento automatico dati ", Updated="04-2-20" WHERE IDDown=7;
# Time: 040301 18:50:59
# User@Host: root[root] @ localhost []
ALTER TABLE Download ADD vrs CHAR(10);
# Time: 040301 19:02:13
# User@Host: pippo[pippo] @ localhost []
UPDATE Download SET IDuser=149, Descrizione="Aggiornamento database", Updated="04-2-28", vrs="1.0.5" WHERE IDDown=8;
# Time: 040301 19:02:43
# User@Host: rt[rt] @ localhost []
DELETE FROM Download WHERE IDDown=7;
.....
Ecco quindi il meccanismo di recupero fino al tempo presente: da un backup recuperate la situazione dei databases fino ad un certo momento; quindi fate eseguire a MySQL queste query per aggiungere i comandi che riportano il database fino all'ultima modifica eseguita. Per questo è sufficiente
mysql -p < /var/log/queries.00n
dove n è il numero del log di query da eseguire.
E' opportuno sincronizzare da cron i backups e l'aggiornamento dei log: questo può essere fatto con uno script che:
1. Arresti il server MySQL (per impedire modifiche dagli utenti durante il backup);
2. Esegua il backup dei dati;
3. Rilanci il server MySQL.
In tal modo l'ultimo backup, seguito dall'esecuzione dell'ultimo log delle query, ripristinerà integralmente i databases.
C'è un'ultima cosa: ad ogni riavvio, MySQL crea un file di log queries.00n
con n numero progressivo. Se non si vuole mantenere traccia di tutti questi logs (e si vuole evitare l'affollamento del disco), è bene creare una rotazione di questi. Farlo con logrotate è un po' un problema, perchè la numerazione progressiva di logrotate rischia di creare conflitto con quella di MySQL. Si può allora fare uno script in bash di questo tipo:
file /usr/bin/mysqlrotate:
#!/bin/bash
MYPATH="/var/log/mysql/queries"
MAX=9
if [ -e $MYPATH.00$MAX ]
then
rm $MYPATH.001
N=2
while [ $N -le $MAX ]
do
M=`expr $N - 1`
mv $MYPATH.00$N $MYPATH.00$M
N=`expr $N + 1`
done
fi
Questo script mantiene fino a 9 logs successivi; basta modificare la variabile MAX per averne di pių. Poichè MySQL crea un nuovo log ad ogni riavvio, può essere opportuno inserirlo direttamente nello script di avvio di MySQL stesso, in genere /etc/init.d/mysql
; basterà cercare il punto del case di start, ed aggiungere prima di ogni altra cosa la chiamata allo script di rotazione dei log:
....
case "$mode" in
'start')
# Start daemon
/usr/bin/mysqlrotate
if test -x $bindir/mysqld_safe
then
...