MariaDB Galera Cluster - Backup and Restore

This page covers backup and restore procedures for MariaDB Galera Clusters.

This page targets MariaDB 11.4.

Two complementary tools are used depending on the scope of the operation:

Tool Use Case Characteristics

mariadb_backup

Full cluster backup and restore

Physical hot backup. Fast backup and restore. Galera-aware (captures cluster position). Always backs up the entire instance.

mariadb_dump

Single database backup and restore

Logical backup as SQL statements. Slower on large datasets but supports granular, per-database operations. Suitable for targeted restores during application updates.

For full cluster restores - for example after data corruption or a disaster recovery scenario - always use mariadb_backup. Use mariadb_dump only for targeted single-database operations.

Backups

Full Cluster Backup with mariadb_backup

mariadb_backup performs a hot backup directly at the storage engine level. The cluster node remains online and in the cluster throughout the entire backup process. No quorum impact occurs under normal conditions.

The provided backup script supports both full and incremental backups. It automatically decides whether to take a full or incremental backup based on the configured cycle interval: if the last full backup is older than FULLBACKUPCYCLE seconds, a new full backup is taken; otherwise an incremental backup is created against the latest full.

Install required packages

The backup tooling is not pre-installed on any supported distribution. Distribution default repositories either do not carry MariaDB 11.4 at all, or ship an older incompatible version. Install from the official MariaDB repository on all supported platforms.

If you have not already configured the MariaDB repository during cluster setup, run the repository setup script first. The same script works across all supported distributions and detects the OS automatically:

curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup \
  | sudo bash -s -- --mariadb-server-version=mariadb-11.4 --skip-maxscale

Then install the required packages on the designated backup node:

Ubuntu 24.04
sudo apt-get install -y mariadb-backup
RHEL 9+
sudo dnf install -y MariaDB-backup
openSUSE 15.6 / 16
sudo zypper install -y MariaDB-backup
On RPM-based distributions (RHEL, openSUSE) the package name is MariaDB-backup with a capital M. On Ubuntu it is mariadb-backup in lowercase. Both install the same tool.

Verify the installed version matches your cluster before proceeding:

mariadb-backup --version

Backup user

Create a dedicated backup user in MariaDB on any one cluster node. Galera will replicate it to all nodes automatically.

CREATE USER 'mariabackup'@'localhost' IDENTIFIED BY 'your_secure_password'; ¹
GRANT CONNECTION ADMIN, SLAVE MONITOR ON *.* TO 'mariabackup'@'localhost';
GRANT RELOAD, PROCESS, LOCK TABLES, BINLOG MONITOR ON *.* TO 'mariabackup'@'localhost';
FLUSH PRIVILEGES;

1. Replace your_secure_password with a strong password and update the backup script accordingly.

The 'mariabackup'@'localhost' user grants access via the local Unix socket only. The backup script connects through the Unix socket and does not use TCP, so no host or port configuration is needed or used.
Backup storage

The backup directory must be accessible and writable by the mysql system user on the node running the backup script.

mkdir -p /mariadb_backup
chown mysql:mysql /mariadb_backup
If you plan to run the backup script on multiple nodes (for redundancy), the backup directory must be on shared network storage mounted to all nodes with mysql user read/write access. For single-node backup execution, local storage is sufficient.

Configure the backup script

Download the backup script and place it on the designated backup node:

You can download the script here.
sudo cp backup_galera_cluster_full.sh /usr/local/bin/backup_galera_cluster_full.sh
sudo chmod 755 /usr/local/bin/backup_galera_cluster_full.sh

Open the script and configure the following variables at the top:

MYSQL_USER=mariabackup ¹
MYSQL_PASSWORD=your_secure_password ²
BACKDIR=/mariadb_backup ³
FULLBACKUPCYCLE=86400 ⁴
KEEP=3 ⁵

1. The backup user created in the previous step.

2. The password for the backup user.

3. Path to the backup directory configured above.

4. Interval in seconds between full backups. 86400 = 1 day, 604800 = 7 days.

5. Number of full backup cycles to retain. Backups older than FULLBACKUPCYCLE * (KEEP + 1) seconds are automatically deleted.

Schedule the backup

On the designated backup node, add the script to the mysql user’s crontab:

crontab -u mysql -e

Add the following entry to trigger the backup script every 2 hours:

0 */2 * * * timeout -k 90 3600 /usr/local/bin/wsrep_sst_backup_mtg.sh

With FULLBACKUPCYCLE=86400 and a 2-hour cron interval, the script will take one full backup per day and up to 11 incremental backups throughout the day.

timeout -k 90 3600 instructs the system to stop the script after 1 hour and forcefully kill it after a further 90 seconds if it is still running. Adjust the timeout value if your database size requires longer backup windows.

Single Database Backup with mariadb_dump

Use mariadb_dump when you need to back up a specific database — for example, before updating a single application component, or to enable recovery from accidental data loss in one schema without affecting the rest of the cluster.

mariadb_dump produces a plain SQL file that can be restored into any running MariaDB instance. The --single-transaction flag ensures a consistent snapshot via InnoDB’s MVCC mechanism without locking tables. The --hex-blob flag ensures binary BLOB data is safely encoded in the output, which is recommended for all MTG databases.

Backup a single database

mariadb-dump \
  --single-transaction \
  --hex-blob \
  --routines \
  --events \
  --user=<admin_user> \
  --password \
  <database_name> > /mariadb_backup/dump_<database_name>_$(date +%F).sql

Replace <admin_user> with a MariaDB user that has SELECT, SHOW VIEW, TRIGGER, LOCK TABLES, and EVENT privileges on the target database. Replace <database_name> with the name of the database to back up.

Backup all databases

mariadb-dump \
  --single-transaction \
  --hex-blob \
  --routines \
  --events \
  --all-databases \
  --user=<admin_user> \
  --password \
  > /mariadb_backup/dump_all_$(date +%F).sql
An all-databases logical dump is provided here for completeness. For full cluster backup and restore, the mariadb_backup physical backup approach described above is strongly preferred due to significantly faster restore times.

Restores

Full Cluster Restore

A full cluster restore replaces all data on the target node and re-initialises the cluster from that node. Stop all application services and all MariaDB nodes before proceeding.

Step 1 - Stop all services and nodes

  1. Stop all application services that connect to the database on all hosts.

  2. Stop MariaDB on all cluster nodes:

    systemctl stop mariadb.service

Step 2 - Run the restore script

Place the restore_galera_cluster_full.sh script inside the BACKDIR folder and execute it on the node you want to restore to:

cd /mariadb_backup
sudo ./restore_galera_cluster_full.sh

The script will:

  • Present an interactive selection of available full backups and their incrementals, allowing you to choose exactly which point in time to restore to.

  • Move the existing /var/lib/mysql data directory to /var/lib/mysql_<timestamp> as a safety copy.

  • Copy the prepared backup into /var/lib/mysql.

A successful run looks like this:

============================================================
 MariaDB Galera Cluster Restore
============================================================
Backup source:  /mariadb_backup
Data directory: /var/lib/mysql
Working dir:    /tmp/mariadb_restore.aX3kQp

Available full backups (newest first):

  [1] Full backup: /mariadb_backup/base/2026-03-06_02-00-01
  [2] Full backup: /mariadb_backup/base/2026-03-05_02-00-00
  [3] Full backup: /mariadb_backup/base/2026-03-04_02-00-03
  [0] Abort restore

Enter selection [0-3]: 1

Available incremental backups for selected full (oldest first):

  [0] Do not apply any incrementals (restore full backup only)
  [1] Apply up to: 2026-03-06_04-00-00
  [2] Apply up to: 2026-03-06_06-00-01
  [3] Apply up to: 2026-03-06_08-00-00

Apply how many incrementals? [0-3]: 3

--- Restore plan -----------------------------------------------
  Full backup:            2026-03-06_02-00-01
  Incrementals to apply:  3
    - 2026-03-06_04-00-00
    - 2026-03-06_06-00-01
    - 2026-03-06_08-00-00
  Data dir to replace:    /var/lib/mysql
----------------------------------------------------------------

Proceed with restore? This will replace /var/lib/mysql. [yes/N] yes

Decompressing: /mariadb_backup/base/2026-03-06_02-00-01/backup.stream.gz
Preparing full backup...
Applying incremental: 2026-03-06_04-00-00
Applying incremental: 2026-03-06_06-00-01
Applying incremental: 2026-03-06_08-00-00
Moving existing data directory to: /var/lib/mysql_2026-03-06_09-15-00
Copying backup into: /var/lib/mysql
Restoring ownership of /var/lib/mysql to mysql:mysql

============================================================
 Restore completed in 142 seconds at Thu Mar  6 09:17:22 UTC 2026.
============================================================
You can download the script here.

Step 3 - Bootstrap the cluster from the restored node

On the restored node, bootstrap a new Galera cluster:

galera_new_cluster

Verify the node has started correctly before proceeding:

journalctl -n 100 -f -u mariadb.service

Step 4 - Rejoin remaining nodes

Once the bootstrapped node is confirmed healthy, start MariaDB on all other nodes one at a time:

systemctl start mariadb.service
When a node rejoins the cluster it performs a State Snapshot Transfer (SST) to synchronise its data with the bootstrapped node. Depending on the size of your databases, this process can take a significant amount of time. Do not start the next node until the current one reports Synced.

Verify each node has completed SST and is fully synchronised before starting the next:

SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment';

The value should read Synced on every node before restarting application services.

Step 5 - Restart application services

Start all application services that connect to the database on all hosts.

Single Database Restore

A logical restore runs the SQL statements from the dump file against the running cluster. Galera will replicate all changes to all nodes automatically — you do not need to stop the cluster or other nodes.

Restoring a database will overwrite its current contents. Ensure you have a recent backup before proceeding, and stop or quiesce any application services that write to the target database during the restore.

If the target database does not yet exist on the cluster, create it first:

CREATE DATABASE <database_name>
  CHARACTER SET utf8
  COLLATE utf8_unicode_ci;

Then restore from the dump file:

mariadb \
  --user=<admin_user> \
  --password \
  <database_name> < /mariadb_backup/dump_<database_name>_<date>.sql

After the restore completes, verify replication has propagated to all nodes by checking a known record or row count on a second cluster node before restarting application services.

Backup Retention and Scheduling Reference

The following table summarises the relationship between the backup script variables and the cron schedule, using the recommended defaults as an example:

Variable / Setting Recommended Default Effect

FULLBACKUPCYCLE

86400 (1 day)

A new full backup is created once per day.

KEEP

3

Full backups older than 4 days (FULLBACKUPCYCLE * (KEEP + 1)) are automatically deleted, along with their incrementals.

Cron interval

Every 2 hours

11 incremental backups are created per day between full backups.

Effective retention

~4 days of full backups, each with up to 11 incrementals

Provides point-in-time recovery granularity of ~2 hours within the retention window.

Test your restore procedure regularly. A backup that has never been restored is an untested backup.