|
Lightweight 0.20260625.0
|
This page explains how the backup engine (Lightweight::SqlBackup::Backup / Restore) works: its pipeline, parallelism model, memory and disk profile, fault tolerance, and the consistency guarantees you can (and cannot) expect. For the on-disk archive layout, see sql-backup-format.md; for the CLI, see dbtool.md (dbtool backup / dbtool restore).
A backup is a single zip archive containing:
metadata.json — schema description (tables, columns, types, row counts),checksums.json — SHA-256 per data chunk,data/<table>/NNNN_SS.msgpack — the table data, split into self-contained msgpack chunks (NNNN = window index, SS = sub-chunk within the window).Backup and restore work against SQLite3, Microsoft SQL Server, and PostgreSQL through ODBC; all per-DBMS SQL differences are handled internally.
[lo, hi]: the planner runs SELECT MIN(pk), MAX(pk) (an index seek) and divides the span into windows of about rowsPerChunk keys, capped at 1024 windows per table — sparse key spaces (e.g. snowflake-style IDs) get proportionally wider windows instead of millions of empty ones. Each window is an independent chunk, so one big table is read by many workers concurrently.Parallel data export. concurrency worker threads, each with its own pooled database connection, drain a shared chunk queue. Workers fetch rows (bulk array-fetch where possible, row-by-row otherwise), encode them to msgpack, hash, and add the chunk files to the archive. Chunk filenames are assigned at plan time, so workers never coordinate on naming, and chunks may complete in any order.
Array-fetch coverage (one driver round-trip per block of rows instead of one SQLGetData per cell — the dominant cost on remote servers): integer family, Real, Bool, Varchar/Char, Decimal, NVarchar/NChar (UTF-16 bound), Date/DateTime/Timestamp (native structs) on all databases; Time and Guid additionally on SQL Server and PostgreSQL. Tables containing LOBs (varchar(max), text, binary) fall back to the row-by-row path. The per-cursor fetch-buffer memory is capped (~4 MB per worker); wide tables automatically read fewer rows per round-trip instead of exhausting RAM.
metadata.json and checksums.json are written, and the archive is closed. The close only streams already-compressed bytes, so it takes seconds even for very large backups.Restore is chunk-order-independent: it enumerates data/<table>/*.msgpack entries and tracks completion by per-table chunk count, so parallel, out-of-order backups restore exactly like sequential ones.
RAM usage is bounded and independent of database size. Each worker buffers at most chunkSizeBytes (default 10 MB) of encoded rows; flushed chunks go into the worker's private temp archive under <output>.zip.tmp/, which is sealed (compressed in the worker thread) every workerArchiveBytes (default 256 MB) of input. The memory ceiling is therefore about concurrency × workerArchiveBytes plus fetch buffers — and because the temp archives hold compressed data, the extra disk needed during the run is only about the size of the final archive itself. The temp directory is removed automatically when the backup finishes (also on failure).
RetrySettings). A PK-window chunk re-reads just its own window; rows already counted are not double-reported, and chunk files are rewritten in place (ZIP_FL_OVERWRITE), so retries are idempotent.checksums.json and verified on restore.The backup runs online, without a global snapshot or table locks. If the database is being written to during the run:
MAX(pk) after a table was planned are not included;For a strictly consistent backup, run against a quiesced database, a snapshot, or a restored replica.
| Knob | Default | Effect |
|---|---|---|
concurrency (jobs) | caller-defined | Worker threads and database connections. The export phase is mostly network/IO-bound, so more jobs ≈ more concurrent result streams. |
BackupSettings::rowsPerChunk | 100 000 | Target keys per PK window. Smaller = finer load balancing, more files; larger = fewer round-trips per table. |
BackupSettings::chunkSizeBytes | 10 MB | Byte threshold per chunk file flush; sets data-file granularity. |
BackupSettings::workerArchiveBytes | 256 MB | Uncompressed input per worker temp archive before it is sealed (compressed). Bounds worker memory at ~jobs × workerArchiveBytes; lower it on memory-constrained machines. |
BackupSettings::method / level | Deflate / 6 | Compression method and level (applied at archive close). |
RetrySettings | sensible defaults | Max retries and backoff for transient errors. |
dbtool backup / dbtool restore CLI usage.