From 11e0f05cd33ca966140ab683cfa4969fd6668203 Mon Sep 17 00:00:00 2001 From: Toni Spets Date: Wed, 15 Nov 2023 04:30:41 +0200 Subject: [PATCH] Use safe checkpointing before snapshots The intention of the code is to do a checkpoint before starting to write out the snapshot. Executing a manual checkpoint will at worst make Litestream lose the track of the WAL as it will in specific circumtances flush out the single page in the WAL file out. Using the public checkpoint function of the database to issue a managed passive checkpoint will ensure the sequence table is written after and the position of the WAL isn't lost. Fixes #521 --- replica.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/replica.go b/replica.go index bf858836..6211200b 100644 --- a/replica.go +++ b/replica.go @@ -477,16 +477,16 @@ func (r *Replica) Snapshot(ctx context.Context) (info SnapshotInfo, err error) { r.muf.Lock() defer r.muf.Unlock() - // Prevent checkpoints during snapshot. - r.db.BeginSnapshot() - defer r.db.EndSnapshot() - // Issue a passive checkpoint to flush any pages to disk before snapshotting. - if _, err := r.db.db.ExecContext(ctx, `PRAGMA wal_checkpoint(PASSIVE);`); err != nil { + if err := r.db.Checkpoint(ctx, CheckpointModePassive); err != nil { return info, fmt.Errorf("pre-snapshot checkpoint: %w", err) } - // Acquire a read lock on the database during snapshot to prevent checkpoints. + // Prevent internal checkpoints during snapshot. + r.db.BeginSnapshot() + defer r.db.EndSnapshot() + + // Acquire a read lock on the database during snapshot to prevent external checkpoints. tx, err := r.db.db.Begin() if err != nil { return info, err