Indice dei contenuti dell'articolo:
Nel mondo dei database, il backup non è mai un argomento banale. Molti amministratori pensano di essere al sicuro perché hanno un dump giornaliero, uno snapshot del volume o una copia notturna del datadir. In realtà, quando si lavora con sistemi in produzione, il problema non è soltanto “avere un backup”, ma poter tornare esattamente al momento desiderato, riducendo al minimo la perdita di dati e limitando il fermo servizio. È qui che entra in gioco il PITR, acronimo di Point In Time Recovery.
Il PITR permette di ripristinare un database MariaDB non semplicemente allo stato dell’ultimo backup disponibile, ma a un preciso istante temporale successivo al backup. Questo è fondamentale quando si verifica un errore umano, una query distruttiva, un aggiornamento applicativo difettoso, una cancellazione accidentale o una compromissione applicativa che modifica dati in modo indesiderato. In tutti questi casi, il ripristino del solo backup potrebbe essere insufficiente: se il backup è delle 02:00 e l’errore avviene alle 14:36, tornare alle 02:00 significherebbe perdere oltre dodici ore di modifiche legittime.
Con un PITR correttamente progettato, invece, si può ripristinare il backup delle 02:00 e poi riapplicare tutte le modifiche successive fino, ad esempio, alle 14:35:59, cioè un secondo prima della query dannosa. Il concetto è semplice, ma richiede una configurazione preventiva: non si può improvvisare un Point In Time Recovery dopo l’incidente se i log necessari non sono stati prodotti e conservati.
Cos’è realmente il PITR in MariaDB
MariaDB non effettua un PITR “magico” partendo dal nulla. Il meccanismo si basa sull’unione di due elementi: un backup consistente e i binary log. Il backup rappresenta una fotografia del database in un determinato momento. I binary log, invece, registrano gli eventi di modifica avvenuti dopo quella fotografia: insert, update, delete, alter table, create table e, più in generale, tutte le operazioni che cambiano lo stato dei dati.
Il flusso logico è quindi il seguente: si prende un backup valido, lo si ripristina su un datadir pulito, si identifica la posizione binlog corrispondente al momento del backup e si riapplicano i binlog fino al punto desiderato. Il punto di arresto può essere definito tramite data e ora, tramite posizione nel binary log oppure, in architetture più avanzate, tramite GTID. Nel contesto operativo più comune, specialmente su server singoli o ambienti managed non eccessivamente complessi, il ripristino tramite nome file del binlog, posizione e stop-datetime è già più che sufficiente.
Dal punto di vista pratico, il tool di backup fisico più indicato per MariaDB è mariadb-backup, precedentemente conosciuto come mariabackup. È uno strumento pensato per eseguire backup fisici online, riducendo l’impatto sul servizio e producendo una copia del datadir che può essere poi preparata e ripristinata. Per la lettura e la riesecuzione dei binary log si usa invece mariadb-binlog, o in alcuni ambienti il comando compatibile mysqlbinlog.
Prerequisito: abilitare e conservare i binary log
Il primo requisito per fare PITR è avere i binary log attivi. Senza binary log, MariaDB può essere ripristinato soltanto al momento del backup, non a un punto intermedio successivo. Questo è l’errore più comune: si implementa una politica di backup, magari anche corretta, ma ci si dimentica che il PITR richiede la persistenza dei log delle modifiche.
Su un server MariaDB installato su Linux, la configurazione può essere inserita nel file di configurazione principale del server. In ambienti AlmaLinux con pacchetti MariaDB, ad esempio, è frequente lavorare in /etc/my.cnf.d/server.cnf. Un esempio minimale è il seguente:
[mysqld] server_id=1 log_bin=/var/lib/mysql/mariadb-bin binlog_format=ROW sync_binlog=1 expire_logs_days=14
Il parametro server_id è necessario quando si abilita il binary log ed è comunque buona pratica impostarlo in modo esplicito. log_bin definisce il percorso e il prefisso dei file binlog. binlog_format=ROW è generalmente preferibile in ottica di recovery, perché registra le modifiche a livello di riga e riduce le ambiguità tipiche dello statement based logging. sync_binlog=1 migliora la durabilità dei log, a fronte di un possibile costo prestazionale. expire_logs_days, infine, stabilisce per quanti giorni conservare i binlog prima della loro scadenza automatica.
Sulle versioni più recenti può essere preferibile utilizzare una retention espressa in secondi:
[mysqld] server_id=1 log_bin=/var/lib/mysql/mariadb-bin binlog_format=ROW sync_binlog=1 binlog_expire_logs_seconds=1209600
Il valore 1209600 corrisponde a 14 giorni. La scelta della retention deve essere coerente con la frequenza dei backup e con l’RPO desiderato. Se si mantiene un backup full giornaliero ma si cancellano i binlog dopo poche ore, la finestra utile per il Point In Time Recovery diventa inutilmente ridotta. In produzione è inoltre consigliabile copiare i binlog anche fuori dal server principale, perché conservarli soltanto sullo stesso disco del database espone al rischio di perderli insieme al datadir.
Dopo la modifica della configurazione, il servizio va riavviato:
systemctl restart mariadb
È possibile verificare l’attivazione dei binary log con:
SHOW VARIABLES LIKE 'log_bin'; SHOW VARIABLES LIKE 'binlog_format'; SHOW BINARY LOGS;
Se log_bin risulta ON e SHOW BINARY LOGS mostra almeno un file binlog, la base tecnica per il PITR è presente.
Creare un backup fisico con mariadb-backup
Una strategia seria di PITR parte da backup fisici consistenti. Un dump SQL può essere utile in molti scenari, ma su database grandi tende a essere lento sia in fase di esportazione sia in fase di importazione. Un backup fisico con mariadb-backup, invece, copia i file reali del database e consente restore generalmente più rapidi, soprattutto su istanze di dimensioni importanti.
Prima di tutto conviene creare un utente dedicato al backup, evitando di usare l’utente amministrativo principale:
CREATE USER 'backup'@'localhost' IDENTIFIED BY 'PasswordMoltoForteQui'; GRANT RELOAD, PROCESS, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'backup'@'localhost'; FLUSH PRIVILEGES;
Il backup full può essere eseguito in una directory dedicata:
mkdir -p /backup/mariadb/full-$(date +%F) mariadb-backup --backup \ --target-dir=/backup/mariadb/full-$(date +%F) \ --user=backup \ --password='PasswordMoltoForteQui'
Il backup appena prodotto non deve essere considerato immediatamente pronto per il restore. Come avviene con i backup fisici di InnoDB, è necessario eseguire una fase di prepare, che rende il backup consistente applicando le informazioni necessarie dai log interni e portando i file in uno stato ripristinabile.
mariadb-backup --prepare \ --target-dir=/backup/mariadb/full-2026-06-10
Una volta completato il prepare, all’interno della directory del backup si trova un file estremamente importante: xtrabackup_binlog_info. Questo file contiene il nome del binary log e la posizione esatta corrispondenti al backup.
cat /backup/mariadb/full-2026-06-10/xtrabackup_binlog_info
Un output tipico può essere:
mariadb-bin.000123 456789
Questo significa che, dopo aver ripristinato quel backup, la riesecuzione dei binlog dovrà partire dal file mariadb-bin.000123 e dalla posizione 456789. È un’informazione da conservare insieme al backup, perché rappresenta il raccordo tra la fotografia del datadir e il flusso successivo delle modifiche.
Ripristinare il backup su un datadir pulito
Il ripristino non dovrebbe essere eseguito alla cieca sul server di produzione. In caso di incidente reale, la procedura più prudente consiste nel ripristinare prima su una macchina separata o su un ambiente isolato, validare i dati recuperati e solo dopo decidere come rientrare in produzione. Questo approccio evita di sovrascrivere definitivamente dati che potrebbero essere ancora utili per analisi, estrazioni parziali o ulteriori tentativi di recovery.
Su un server di restore, dopo aver fermato MariaDB, si può mettere da parte il datadir esistente e prepararne uno vuoto:
systemctl stop mariadb mv /var/lib/mysql /var/lib/mysql.pre-pitr.$(date +%F-%H%M%S) mkdir /var/lib/mysql chown mysql:mysql /var/lib/mysql
A questo punto si copia il backup preparato nel datadir:
mariadb-backup --copy-back \ --target-dir=/backup/mariadb/full-2026-06-10 chown -R mysql:mysql /var/lib/mysql systemctl start mariadb
Dopo l’avvio, MariaDB si troverà nello stato esatto del backup full. Non siamo ancora arrivati al punto temporale desiderato: abbiamo soltanto ricostruito la base da cui partire. Il passo successivo consiste nel riapplicare i binary log.
Applicare i binary log fino al momento desiderato
Supponiamo di voler recuperare il database fino al 10 giugno 2026 alle 14:35:59. Supponiamo inoltre che l’errore sia avvenuto alle 14:36:12, magari a causa di un DROP TABLE o di un DELETE senza clausola WHERE. Il nostro obiettivo è riapplicare tutti gli eventi validi avvenuti dopo il backup, fermandoci prima dell’operazione distruttiva.
Se il file xtrabackup_binlog_info indicava:
mariadb-bin.000123 456789
e i binlog originali sono stati preservati in /var/lib/mysql.pre-pitr.2026-06-10-150000/, possiamo generare un file SQL di recovery in questo modo:
mariadb-binlog \ --start-position=456789 \ --stop-datetime="2026-06-10 14:35:59" \ /var/lib/mysql.pre-pitr.2026-06-10-150000/mariadb-bin.000123 \ /var/lib/mysql.pre-pitr.2026-06-10-150000/mariadb-bin.000124 \ /var/lib/mysql.pre-pitr.2026-06-10-150000/mariadb-bin.000125 \ > /root/pitr-recovery.sql
Il file risultante può quindi essere applicato al database ripristinato:
mariadb < /root/pitr-recovery.sql
Questa operazione replaya gli eventi contenuti nei binlog fino allo stop datetime indicato. Il database finale non sarà quello del backup, ma quello risultante dal backup più tutte le modifiche successive fino al momento scelto.
In scenari delicati, tuttavia, è spesso meglio non fidarsi solo dell’orario. Due transazioni possono essere molto vicine, oppure l’orologio del server può introdurre ambiguità. Per questo motivo, quando possibile, è preferibile ispezionare il binlog e individuare la posizione precisa dell’evento da evitare.
mariadb-binlog \ --base64-output=DECODE-ROWS \ -vv \ /var/lib/mysql.pre-pitr.2026-06-10-150000/mariadb-bin.000124 \ | less
Con questa modalità è possibile leggere gli eventi row-based in forma più comprensibile, cercare l’operazione dannosa e annotare la posizione immediatamente precedente. A quel punto si può usare --stop-position al posto di --stop-datetime:
mariadb-binlog \ --start-position=456789 \ --stop-position=987654 \ /var/lib/mysql.pre-pitr.2026-06-10-150000/mariadb-bin.000123 \ /var/lib/mysql.pre-pitr.2026-06-10-150000/mariadb-bin.000124 \ > /root/pitr-recovery.sql mariadb < /root/pitr-recovery.sql
La posizione binlog è generalmente più precisa dell’orario, perché identifica un punto esatto nel flusso degli eventi.
Esempio tecnico: recupero prima di una cancellazione accidentale
Immaginiamo un database applicativo chiamato ecommerce. Alle 02:00 viene eseguito un backup full con mariadb-backup. Alle 14:36 un operatore esegue per errore:
DELETE FROM ordini;
oppure, in uno scenario ancora più grave:
DROP TABLE ordini;
Il backup full da solo permetterebbe di tornare alle 02:00, ma si perderebbero tutti gli ordini registrati nella mattinata. Con PITR, invece, si procede così: si isola il server o si prepara una macchina di restore, si ripristina il backup delle 02:00, si recupera da xtrabackup_binlog_info la posizione di partenza, si leggono i binlog fino a pochi secondi prima dell’errore e si applica il risultato.
cat /backup/mariadb/full-2026-06-10/xtrabackup_binlog_info
Output:
mariadb-bin.000120 884422
Generazione del replay:
mariadb-binlog \ --start-position=884422 \ --stop-datetime="2026-06-10 14:35:59" \ /safe-binlogs/mariadb-bin.000120 \ /safe-binlogs/mariadb-bin.000121 \ /safe-binlogs/mariadb-bin.000122 \ > /root/ecommerce-pitr.sql
Applicazione:
mariadb ecommerce < /root/ecommerce-pitr.sql
Dopo l’importazione, è necessario verificare la coerenza applicativa: numero di ordini, tabelle correlate, vincoli, dati di pagamento, log applicativi e stato delle code eventualmente collegate. Il PITR ricostruisce il database a livello di eventi MariaDB, ma non sostituisce una validazione funzionale dell’applicazione.
Attenzioni operative e best practice
Il primo errore da evitare è conservare backup e binlog sullo stesso filesystem senza alcuna replica esterna. In caso di guasto disco, ransomware o cancellazione accidentale lato sistema, si rischia di perdere sia la fotografia sia il diario delle modifiche. Una politica corretta dovrebbe prevedere backup locali per restore rapidi, copie remote per disaster recovery e conservazione coerente dei binlog.
Il secondo punto riguarda il test periodico. Una strategia di backup non testata è soltanto una speranza. È necessario provare periodicamente il restore su un ambiente separato, misurare i tempi reali, verificare che i binlog siano presenti e controllare che la procedura arrivi davvero al punto temporale desiderato. Questo permette di stimare RTO e RPO in modo realistico, non teorico.
Il terzo aspetto riguarda la sicurezza. I backup MariaDB contengono dati sensibili, password applicative, informazioni personali e dati transazionali. Devono essere protetti con permessi rigorosi, cifratura quando necessario, accessi limitati e procedure di rotazione. Il PITR è una misura di continuità operativa, ma non deve diventare una nuova superficie di rischio.
Infine, bisogna ricordare che i binlog non sono gratuiti dal punto di vista delle risorse. Occupano spazio, generano I/O e devono essere monitorati. In ambienti con molte scritture, la crescita dei binlog può essere significativa. Per questo è opportuno configurare alert sullo spazio disco, automatizzare la copia remota dei log e definire retention compatibili con il ciclo dei backup.
Conclusione
Il Point In Time Recovery in MariaDB è una delle procedure più importanti per chi gestisce database in produzione. Non basta poter ripristinare “un backup”: bisogna poter ripristinare il dato giusto, nel momento giusto, evitando sia la perdita eccessiva di informazioni sia il ritorno a uno stato già compromesso.
La combinazione di mariadb-backup, binary log e mariadb-binlog consente di costruire una strategia di recovery robusta e relativamente semplice da automatizzare. Il backup fisico fornisce la base consistente, xtrabackup_binlog_info indica il punto da cui ripartire e i binlog permettono di riapplicare le modifiche fino all’istante desiderato.
La vera differenza, però, non la fa il comando usato nel momento dell’emergenza, ma la preparazione precedente: binary log già attivi, retention corretta, copie remote, backup preparati, procedure documentate e test periodici. Il PITR è efficace solo se è stato progettato prima dell’incidente. Dopo, nella migliore delle ipotesi, si può solo scoprire se la strategia di backup era davvero adeguata.
Per approfondire i dettagli implementativi, è utile consultare anche la documentazione ufficiale MariaDB su Point-In-Time Recovery con mariadb-backup, la guida su backup e restore con mariadb-backup e il riferimento di mariadb-binlog.