RonDB training · module 17 of 25 · 18 min

Backup and restore

A transaction-consistent copy of the whole cluster, taken online, and the four steps that bring it back.

Backup · not the same as a checkpoint

Backups vs checkpoints: backups survive disasters and move data

Local checkpoint

  • Continuous, partial, per node.
  • Only that node can use it, with its REDO log.
  • Kept by RonDB, replaced as it goes.

Backup

  • On demand: the whole cluster, consistent at one global checkpoint.
  • Restorable into any cluster: new hardware, other sizes, other versions.
  • Kept by you: archives, upgrades, seeding replication.

Both share one disk write budget, MinDiskWriteSpeed and MaxDiskWriteSpeed; BackupDiskWriteSpeedPct (50) reserves part of it for backups.

docs: rondb_backup.md · code: ConfigInfo.cpp (BackupDiskWriteSpeedPct 50: "Percentage of MaxDiskWriteSpeed to reserve for Backup")

Taking a backup · from the management client

START BACKUP: one command backs up the whole cluster, online

ndb_mgm real output · rondb_global_prepare_primary
START BACKUP
Waiting for completed, this may take several minutes
Node 2: Backup 1 started from node 1
Node 2: Backup 1 started from node 1 completed
StartGCP: 3839 StopGCP: 3845
#Records: 193234 #LogRecords: 12349
Data: 20519789 bytes Log: 1334560 bytes
  • Each backup gets an id: here 1.
  • The backup is consistent at a global checkpoint: here StopGCP 3845.
  • Records came from the scan; log records are changes made while it ran.

docs: rondb_backup.md · rondb_global_prepare_primary.md (the output) · code: mgmclient/CommandInterpreter.cpp (START BACKUP)

START BACKUP · the full syntax

START BACKUP options: the id, encryption, the snapshot point and waiting

START BACKUP [<backup id>] [ENCRYPT [PASSWORD='<password>']]
    [SNAPSHOTSTART | SNAPSHOTEND] [NOWAIT | WAIT STARTED | WAIT COMPLETED]
OptionMeans
<backup id>Your own id instead of the next number
ENCRYPT PASSWORDEncrypted backup files; RequireEncryptedBackup can make it mandatory
SNAPSHOTEND · defaultConsistent at the end of the backup
SNAPSHOTSTARTConsistent at the start
WAIT COMPLETED · defaultThe client waits for the report; NOWAIT and WAIT STARTED return sooner

code: mgmclient/CommandInterpreter.cpp (helpTextStartBackup) · ConfigInfo.cpp (RequireEncryptedBackup) · docs: rondb_backup.md (The START BACKUP command)

The algorithm · a scan plus a log

The backup algorithm: scan every fragment while a log records the changes

StartGCP StopGCP 1 triggers on 2 definitions → .ctl 3 scan every fragment → .Data 4 every change while the scan runs → .log 5 log stops

The backup starts at a global checkpoint, StartGCP: from then on triggers send every change to the backup log.

Table definitions go to the control file first.

Each fragment is scanned into the data file. The scan is not consistent by itself: rows change while it runs. The log has every change.

After the scan, the log stops at a later global checkpoint, StopGCP. Data plus log replayed give exactly the state at StopGCP.

docs: rondb_backup.md (Backup algorithm) · code: backup/Backup.cpp

SNAPSHOTEND or SNAPSHOTSTART · REDO or UNDO

SNAPSHOTEND or SNAPSHOTSTART: the backup shows its end or its start

SNAPSHOTEND · default

  • The log records how to redo each change.
  • Restore applies it forwards after the data.
  • Consistent at StopGCP.

SNAPSHOTSTART

  • The log records how to undo each change.
  • Restore applies it backwards; the log is never compressed, so it can be read from the end.
  • Consistent at StartGCP: the moment you asked for.

docs: rondb_backup.md (Backup algorithm, The START BACKUP command) · code: backup/Backup.cpp (log left uncompressed for SNAPSHOTSTART)

On disk · one set of files per ldm thread

Backup files: every ldm thread writes its own part of the backup

# under BackupDataDir, on data node 1
BACKUP/
  BACKUP-10/
    BACKUP-10-PART-1-OF-4/
      BACKUP-10-0.1.Data   # rows
      BACKUP-10.1.ctl      # definitions
      BACKUP-10.1.log      # changes
    BACKUP-10-PART-2-OF-4/
      …
    BACKUP-10-PART-4-OF-4/
  • Each data node writes only its own fragments: a full backup is the files of all data nodes.
  • One PART directory per ldm thread, written in parallel.

code: src/kernel/blocks/ndbfs/Filename.cpp (BACKUP-%u-PART-%u-OF-%u, BACKUP-%u-%u.%u) · backup/Backup.cpp · docs: rondb_backup.md (Backup file placement) · ids are an illustration

Configuration · and file management

Put backups on their own device: a full disk can stop the cluster

config.iniDefaultWhy
BackupDataDirDataDirA separate device: filling it must not take space from checkpoints
BackupLogBufferSize16M per ldm threadChanges during the backup; if it fills, the backup aborts
CompressedBackupfalseSmaller files, more CPU in io threads
BackupDiskWriteSpeedPct50Share of the write budget kept for backups

Old backups are yours to delete. ABORT BACKUP <id> stops a running backup and deletes its files.

docs: rondb_backup.md (Backup configuration, Backup file management, Aborting a backup) · code: ConfigInfo.cpp (BackupLogBufferSize 16M, CompressedBackup false, BackupDiskWriteSpeedPct 50)

Metadata · what the backup does not cover

Back up MySQL objects with mysqldump

mysqldump \
  --no-data \
  --databases db1 db2 \
  > backup_metadata.sql

# restore it through a MySQL server
mysql < backup_metadata.sql
  • Tables and databases, and also views, stored procedures and triggers, which live in MySQL servers (module 03).
  • Recommended over the backup's own metadata: it goes through MySQL, so all servers and global replication see it.
  • Keep RonDB tables in their own databases to dump only them.

docs: rondb_backup.md (Backing up metadata in RonDB) · rondb_restore.md (Using MySQL dump)

PART 1

Restore

ndb_restore, in four steps.

ndb_restore · into a freshly started cluster

ndb_restore: metadata once, indexes off, data in parallel, indexes back on

1 metadata--restore_meta · once 2 indexes off--disable-indexes · once 3 --restore-data · backup node 1 3 --restore-data · backup node 2 3 … one per backup node 4 indexes on--rebuild-indexes · once

Restore into an empty cluster, after an initial start. The target may have a different number of data nodes: rows are hashed to its partitions.

docs: rondb_restore.md (Commands to run) · code: tools/restore/restore_main.cpp

Commands · backup 10 of a two-node cluster

ndb_restore commands: each names the server, node id, backup id and path

R="ndb_restore --connectstring=mgm_host --backupid=10 --backup-path=/backup/path/dir"

$R --nodeid=1 --restore_meta --no-restore-disk-objects    # 1 once
$R --nodeid=1 --disable-indexes                           # 2 once
$R --nodeid=1 --restore-data &                            # 3 per node,
$R --nodeid=2 --restore-data &                            #   in parallel
wait
$R --nodeid=1 --rebuild-indexes                           # 4 once
  • --nodeid names the node that took the backup, whose files are read.
  • Each call finds the PART directories itself and restores them with a thread each; --parallelism defaults to 128 transactions.
  • After step 1, run SHOW TABLES on the MySQL servers so they see the new tables.

docs: rondb_restore.md (Commands to run, Restoring metadata) · code: restore_main.cpp (parallelism default 128; PART-x-OF-y detection) · the shell wrapper is an illustration

Indexes · off during the data step

Why indexes are off: restored data is inconsistent until the last log record

The scan

Rows were scanned at different moments: two rows may briefly hold the same unique value.

So

With unique indexes enabled, inserts could fail mid-restore. Disabling indexes is a must when unique indexes exist.

Meanwhile

Only primary key lookups and full table scans give correct results. Keep applications away until step 4 is done.

docs: rondb_restore.md (Disabling indexes, Commands to run)

ndb_restore options · pick and transform

ndb_restore options: restore part of a backup, under other names, or with changes

OptionDoes
--include-databases · --exclude-tables …Restore only some databases or tables
--rewrite-database=old,newRestore into another database name
--remap-column · --allow-pk-changesTransform column values; allow primary key changes
--num-slices · --slice-idSplit one node's data over several ndb_restore processes
--decrypt --backup-passwordRead an encrypted backup
--include-stored-grants · --restore-privilege-tablesUsers stored in RonDB

code: storage/ndb/tools/restore/restore_main.cpp (option table) · docs: rondb_restore.md (Partial restore)

Global replication · start a replica from a backup

Seeding a replica: a restore tells it where in the binary log to start

  1. Back up the primary cluster; the backup ends at a known epoch (from StopGCP).
  2. Restore all four steps on the replica with --no-binlog: the restore itself must not be replicated.
  3. Add --restore-epoch to the last step: it writes the epoch into ndb_apply_status with server_id 0.
  4. Start replication from that epoch: nothing lost, nothing applied twice (module 24).

docs: rondb_restore.md (restore with --no-binlog and --restore-epoch) · rondb_global_prepare_primary.md

Recap · module 17

What to take away

  • START BACKUP: online, consistent at a global checkpoint.
  • A scan plus a log: SNAPSHOTEND rolls forward, SNAPSHOTSTART rolls back.
  • One PART directory per ldm thread, on every data node; use a separate device.
  • Restore: metadata, indexes off, data per node in parallel, indexes on.
  • --no-binlog and --restore-epoch seed global replication.

Next · 18 · Operations