2010-08-27 3 views
5

Nel SQLite documentation nella funzione di registro write-ahead introdotto nella versione 3.7, ci sono alcuni commenti che mi hanno confuso un po '.Quanto è sicuro SQLal WAL in caso di interruzioni di corrente?

La pagina collegata indica che "la sincronizzazione del contenuto sul disco non è necessaria, purché l'applicazione sia disposta a sacrificare la durata a seguito di una perdita di alimentazione". Poi un paio di paragrafi in basso, dice "Il checkpoint richiede operazioni di sincronizzazione per evitare la possibilità di danneggiamento del database dopo una perdita di potenza o un riavvio".

Così è il mio database a maggior rischio di corruzione in caso di interruzione dell'alimentazione se uso WAL?

risposta

4

non v'è alcun aumento del rischio di corruzione con WAL (dal momento che utilizza le operazioni di sincronizzazione quando checkpoint).

Tuttavia, se c'è un crash (perdita di potenza o riavvio rigido) si perde qualsiasi transazioni dall'ultimo checkpoint, questo è il significato di "sacrificare la durabilità".

+3

So che questa risposta è vecchia, ma ha un errore piuttosto importante. Non perderai le transazioni dall'ultimo checkpoint, perderai le transazioni che non sono ancora state completamente scritte sul WAL. Se sincrono = NORMALE, non attende un fsync() durante la scrittura della transazione nel WAL, quindi potresti perdere quella transazione se perdi energia prima che sia completamente scritta. Una volta nel WAL, non andrà perso, indipendentemente dal checkpoint. –

+1

Fino al 2016-02-17 https://www.sqlite.org/docsrc/info/3540d671bcc4835c la documentazione SQLite diceva che synchronous = NORMAL per impostazione predefinita in modalità WAL ... ora dice synchronous = FULL - impostazione predefinita molto più sicura. Quindi, perderai le transazioni prima del checkpoint solo se imposti la modalità sincrona = NORMALE –

5

Per rispondere in modo completo, è necessario sapere a che cosa è impostato PRAGMA synchronous, poiché questo influisce quando viene chiamato fdatasync() e quindi quando i buffer vengono scaricati sull'unità fisica.

Quando si cita "fino a quando l'applicazione è disposta a sacrificare la durata a seguito di una perdita di alimentazione", ciò si riferisce al fatto di avere synchronous=NORMAL. Qui il WAL viene sincronizzato su disco solo quando si verifica il checkpoint (uno fdatasync() per il WAL e uno per il DB principale dopo la sua fusione). Dovresti essere protetto dalla corruzione abbastanza bene, ma potrebbero esserci delle scritture che non sono mai arrivate al piatto e che sono andate perse: da qui la durata perduta. Il rialzo però è molto meno del lento fdatasync() per sincronizzare realmente i dati.

Per ottenere la migliore resilienza dai dati persi, è possibile che sia necessario synchronous=FULL. Questo guadagna la durabilità, ma il costo è uno fdatasync() per transazione di scrittura. Tuttavia, questa è ancora migliore della modalità non WAL dove ci sarebbero due chiamate fdatasync() - una per il giornale delle transazioni e una per il DB principale.

0

Finché le chiamate di sincronizzazione al sistema operativo funzionano perfettamente, si ha il rischio zero di un db danneggiato. Tuttavia, questo può essere o non essere il caso - consultare la documentazione sqlite per una spiegazione più lunga a riguardo.

Per correggere Doug Currie (vedere Post di MattR): si rischia solo di perdere le transazioni se @ synchronous = NORMAL @. Se @ synchronous = FULL @ (che è l'impostazione predefinita) non sacrifichi la durabilità. Vedi http://www.sqlite.org/draft/wal.html per maggiori dettagli su questo.

credo WAL nel diario è di fatto più sicuro che nel diario 'classico' (in caso di non perfetta sincronizzazione del sistema), in quanto la possibilità che il db fa qualcosa critica in un dato momento è più basso per quanto ho capito WAL nel diario. Tuttavia, al momento non ho dati rigidi per supportare questo.