I backup e la finestra di ripristino¶
La storia di un target è una catena: backup completi pianificati e, tra l'uno e l'altro, un flusso di modifiche continuo (WAL di Postgres, binlog di MySQL). Qualsiasi secondo coperto da un backup completo e dalle modifiche successive può essere ripristinato. Questo intervallo è la finestra point-in-time.
gantt
dateFormat YYYY-MM-DD HH:mm
axisFormat %a %d
section Full backups
daily full :milestone, 2026-10-01 02:07, 0d
daily full :milestone, 2026-10-02 02:07, 0d
daily full :milestone, 2026-10-03 02:07, 0d
daily full :milestone, 2026-10-04 02:07, 0d
section Change stream
WAL / binlog segments :active, 2026-10-01 02:07, 2026-10-04 18:00
Backup completi¶
| Engine | Modalità | Tool | Ripristino |
|---|---|---|---|
| Postgres 15–17 | physical (predefinita) |
pg_basebackup -Ft -X fetch tramite il protocollo di replica |
backup di base + replay del WAL al secondo |
| Postgres 15–17 | logical |
pg_dump -Fc, un oggetto per database; esclusione di tabelle ed esportazioni selettive |
pg_restore, più replay del WAL tramite una catena fisica se esiste |
| MySQL 8.4 | logical |
mysqldump --single-transaction --source-data=2 (routine, eventi, trigger) |
caricamento + replay del binlog al secondo |
Ogni backup registra un inventario: database, tabelle, colonne, indici, stime delle righe e dimensioni, e la
versione delle migrazioni quando esiste una tabella delle migrazioni. È ciò che la console e tenax diff
confrontano.
Il flusso di modifiche¶
Ogni target con point-in-time recovery ha uno streamer:
- Postgres: il receiver WAL di Tenax su uno slot di replica fisica (ADR 0005). Lo slot garantisce che nessun WAL vada perso mentre lo streamer si riavvia.
- MySQL:
mysqlbinlog --read-from-remote-server --raw --stop-neverdalla posizione del binlog dell'ultimo backup completo.
I segmenti vengono caricati man mano che si completano, e il segmento ancora in scrittura viene caricato ogni
partialInterval (predefinito 60 s), così è ripristinabile anche l'ultimo minuto. Ogni segmento porta un riepilogo:
commit, insert, update e delete per tabella, DDL e, facoltativamente, anteprime mascherate delle righe.
Se il flusso si interrompe (uno slot viene perso, un binlog viene eliminato), Tenax marca la catena come interrotta,
genera un alert (TenaxStreamChainBroken), avvia una nuova catena ed esegue subito un backup completo (motivo
chain-restart). La vecchia finestra resta ripristinabile fino al punto di interruzione.
Conservazione¶
I backup completi vengono conservati per livelli; i segmenti vengono conservati solo fin dove serve alla finestra; la garbage collection rimuove tutto il resto, ma mai ciò che è bloccato.
| Preset | Finestra | Giornalieri | Settimanali | Mensili | Annuali |
|---|---|---|---|---|---|
prod |
7 giorni | 14 | 8 | 12 | 5 |
dev |
3 giorni | 7 | 4 | 3 | 0 |
critical |
14 giorni | 30 | 12 | 24 | 7 |
Il primo backup completo confermato di un giorno è il giornaliero di quel giorno; di una settimana ISO il suo
settimanale; e così via. Un backup può appartenere a più livelli; non viene copiato nulla. I blocchi
(tenax pin <id> --reason …) trattengono un backup indipendentemente dai livelli. La GC scrive il suo piano nel
bucket prima di eliminare, elimina i manifest prima dei dati e ripulisce gli upload orfani e incompleti dopo un
giorno.
Formato di archiviazione¶
<store prefix>/<org>/<project>/<namespace>/<target>/
full/<backup-id>/manifest.json # written last: the commit marker
full/<backup-id>/data/<database>.zst.age # dumps or the base backup tar
full/<backup-id>/inventory.json.zst.age # also readable with the catalog key
full/<backup-id>/tags.json # tiers, pins, verification results
stream/…/<segment>.zst.age # WAL / binlog segments and their summaries
stream/position.json # the streamer's confirmed position
- Compressione: zstd al livello della policy, una sola volta, prima della cifratura; attiva per impostazione
predefinita (ADR 0013).
compression.algorithm: nonesalva i dati così come sono. - Cifratura: ogni oggetto viene cifrato con age lato client verso i destinatari dello store. Il bucket non vede mai dati in chiaro.
- Integrità: dimensione e SHA-256 di ogni oggetto sono nel manifest e vengono verificati a ogni lettura.
- Commit: un backup esiste solo quando
manifest.jsonè stato scritto. Un crash prima di quel momento lascia oggetti orfani che la GC rimuove, mai un backup che sembra completo.
Controllo del carico¶
I backup non competono mai alla cieca con la produzione: slot per host, per target e globali, un limite di banda, una
priorità, un jitter sulle pianificazioni e una protezione dal carico che rinvia un backup completo finché il
server ha troppe connessioni attive, troppo ritardo di replica o transazioni di lunga durata. Tutto si imposta nella
BackupPolicy.