> For the complete documentation index, see [llms.txt](https://mariadb.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mariadb.com/docs/galera-cluster/high-availability/state-snapshot-transfers-ssts-in-galera-cluster/manual-sst-of-galera-cluster-node-with-mariadb-backup.md).

# Manual SST of Galera Cluster Node With mariadb-backup

Sometimes it can be helpful to perform a "manual SST" when Galera's [normal SSTs](/docs/galera-cluster/high-availability/state-snapshot-transfers-ssts-in-galera-cluster/introduction-to-state-snapshot-transfers-ssts.md) fail. This can be especially useful when the cluster's [`datadir`](/docs/server/server-management/variables-and-modes/server-system-variables.md#datadir) is very large, since a normal SST can take a long time, keeping the donor in a not fully synced state for the duration of the transfer.

A manual SST essentially consists of taking a backup of the donor, loading the backup on the joiner, and then manually editing the cluster state on the joiner node. This page will show how to perform this process with [mariadb-backup](/docs/server/server-usage/backup-and-restore/mariadb-backup.md).

## Process <a href="#process" id="process"></a>

{% stepper %}
{% step %}

### Check the nodes

Ensure you understand the version compatibility between your nodes. For a standard manual SST, the donor and joiner should run the same `mariadb-backup` version.

{% hint style="info" %}
**For major version upgrades (e.g., 10.6 to 11.4)**

The versions will differ. In this scenario, you **must** use **Method B** in the next step because a newer `mariadb-backup` binary cannot prepare a raw backup generated by an older major version.
{% endhint %}

```bash
mariadb-backup --version
```

{% endstep %}

{% step %}

### Prepare and Transfer the Backup (Choose ONE Method)

Select the strategy below that best matches your environment's resource constraints and upgrade requirements.

```mermaid
graph TD
    classDef donor fill:#e1f5fe,stroke:#0288d1,stroke-width:2px;
    classDef joiner fill:#e8f5e9,stroke:#388e3c,stroke-width:2px;
    classDef network fill:#fff3e0,stroke:#f57c00,stroke-width:2px,stroke-dasharray: 5 5;

    %% Root Action
    Start["Take Backup on Donor 
    (mariadb-backup --backup)"]:::donor

    %% First Split: Disk vs. Stream
    Start -->|Methods A & B| Disk["Save Raw Backup to Donor Disk"]:::donor
    Start -->|Method C| Stream["Stream Backup via SSH 
    (--stream=mbstream)"]:::network

    %% Method B Path
    Disk -->|Method B| PrepDonor["Prepare Backup on Donor 
    (--prepare)"]:::donor
    PrepDonor --> TransPrep["Transfer Prepared Files to Joiner 
    (rsync/scp)"]:::network

    %% Method A Path
    Disk -->|Method A| TransRaw["Transfer Raw Files to Joiner 
    (rsync/scp)"]:::network

    %% Method C Path
    Stream --> Extract["Extract Stream on Joiner 
    (mbstream -x)"]:::joiner

    %% Convergence for Methods A & C
    TransRaw --> PrepJoiner["Prepare Backup on Joiner 
    (--prepare)"]:::joiner
    Extract --> PrepJoiner
```

#### **Method A: Prepare on the Joiner Node (Standard / Resource-Saving)**

Use this if both nodes are on the same major MariaDB version. This offloads RAM and CPU overhead from the active donor to the joiner.

1. On the donor node, create the backup directory and take the backup:

```bash
BACKUP_DIR=/mariadb_backup
mkdir -p $BACKUP_DIR

DB_USER=sstuser
DB_USER_PASS=password
mariadb-backup --backup --galera-info \
   --target-dir=$BACKUP_DIR \
   --user=$DB_USER \
   --password=$DB_USER_PASS
```

2. On the joiner node, stop MariaDB, create the backup directory:

```bash
systemctl stop mariadb

BACKUP_DIR=/mariadb_backup
mkdir -p $BACKUP_DIR
```

3. From the donor node, transfer the contents of the backup directory to the joiner node. You may use `rsync`, `scp`, or your preferred file transfer method.
4. On the joiner node, prepare the backup:

```bash
mariadb-backup --prepare --target-dir=$BACKUP_DIR
```

#### **Method B: Prepare on the Donor Node (Required for Major Upgrades)**

Use this for cross-version upgrades (e.g., 10.6 to 11.4). The donor's native binary must apply the redo logs before transit, ensuring compatibility.

1\. On the donor node, create the directory, take the backup, and prepare it:

```bash
BACKUP_DIR=/mariadb_backup
mkdir -p $BACKUP_DIR

DB_USER=sstuser
DB_USER_PASS=password
mariadb-backup --backup --galera-info \
   --target-dir=$BACKUP_DIR \
   --user=$DB_USER \
   --password=$DB_USER_PASS

mariadb-backup --prepare --target-dir=$BACKUP_DIR
```

2\. On the joiner node, make sure MariaDB is stopped, create the directory:

```bash
systemctl stop mariadb

BACKUP_DIR=/mariadb_backup
mkdir -p $BACKUP_DIR
```

3. From the donor node, transfer the contents of the backup directory to the joiner node. You may use `rsync`, `scp`, or your preferred file transfer method.

#### **Method C: Streaming Backup (Zero Donor Disk Overhead)**

Use this to avoid using local staging disk space on the donor node, especially when the cluster's `datadir` is very large. A standard manual backup requires enough free disk space on the donor node to hold a complete secondary copy of the data. Streaming avoids this local disk overhead entirely by piping the data directly over SSH

{% hint style="warning" %}
*Do not use for cross-version upgrades.*
{% endhint %}

{% hint style="info" %}
**Prerequisites for Streaming:**

The streaming command on the donor must be executed by `root` or a user in the `mysql` group to be able to read the data directory.

The `OS_USER` on the joiner node must have the executing user's public SSH key added to their `$HOME/.ssh/authorized_keys` file to allow the stream to pipe without a password prompt.
{% endhint %}

1. On the joiner node, make sure MariaDB is stopped and create the target directory:

```bash
systemctl stop mariadb

BACKUP_DIR=/mariadb_backup
mkdir -p $BACKUP_DIR
```

2\. On the donor node, stream the backup directly to the joiner:

```bash
DB_USER=sstuser
DB_USER_PASS=password
OS_USER=dba
JOINER_HOST=dbserver2.mariadb.com
BACKUP_DIR=/mariadb_backup

mariadb-backup --backup --galera-info --stream=mbstream \
   --user=$DB_USER --password=$DB_USER_PASS | \
   ssh ${OS_USER}@${JOINER_HOST} "mbstream -x -C $BACKUP_DIR"
```

3\. On the joiner node, prepare the backup:

```bash
mariadb-backup --prepare --target-dir=$BACKUP_DIR
```

{% endstep %}

{% step %}

### Get the ID

Get the Galera Cluster version ID from the donor node's `grastate.dat` file.

```bash
DATADIR=/var/lib/mysql
cat $DATADIR/grastate.dat | grep version
```

{% endstep %}
{% endstepper %}

For example, a very common version number is "2.1".

{% stepper %}
{% step %}

### Get the node's cluster state

Get the state from the Galera info file in the backup that was copied to the joiner node.

The name of this file depends on the MariaDB version:

* MariaDB 11.4 and later: `mariadb_backup_galera_info`
* MariaDB 11.3 and earlier: `xtrabackup_galera_info`

For MariaDB 11.4 and later:

```bash
cat $BACKUP_DIR/mariadb_backup_galera_info
```

For MariaDB 11.3 and earlier:

```bash
cat $BACKUP_DIR/xtrabackup_galera_info
```

The file contains the values of the [wsrep\_local\_state\_uuid](/docs/galera-cluster/reference/galera-cluster-status-variables.md#wsrep_local_state_uuid) and [wsrep\_last\_committed](/docs/galera-cluster/reference/galera-cluster-status-variables.md#wsrep_last_committed) status variables. The values are written in the following format:

```ini
wsrep_local_state_uuid:wsrep_last_committed
```

For example:

```uri
d38587ce-246c-11e5-bcce-6bbd0831cc0f:1352215
```

{% endstep %}

{% step %}

### Create a `grastate.dat` file

Create the file in the backup directory of the joiner node. The Galera Cluster version ID, the cluster uuid, and the seqno from previous steps will be used to fill in the relevant fields.

For example, with the example values from the last two steps, we could do:

```bash
sudo tee $BACKUP_DIR/grastate.dat <<EOF
# GALERA saved state
version: 2.1
uuid:    d38587ce-246c-11e5-bcce-6bbd0831cc0f
seqno:   1352215
safe_to_bootstrap: 0
EOF
```

{% endstep %}

{% step %}

### Remove contents

Remove the existing contents of the [`datadir`](/docs/server/server-management/variables-and-modes/server-system-variables.md#datadir) on the joiner node.

```bash
DATADIR=/var/lib/mysql
rm -Rf $DATADIR/*
```

{% endstep %}

{% step %}

### Copy contents

Copy the contents of the backup directory to the [`datadir`](/docs/server/server-management/variables-and-modes/server-system-variables.md#datadir) the on joiner node.

```bash
mariadb-backup --copy-back \
   --target-dir=$BACKUP_DIR
```

{% endstep %}

{% step %}

### Check `datadir` permissions

Make sure the permissions of the [`datadir`](/docs/server/server-management/variables-and-modes/server-system-variables.md#datadir) are correct on the joiner node.

```bash
chown -R mysql:mysql $DATADIR/
```

{% endstep %}

{% step %}

### Start the MariaDB Server process on the joiner node.&#x20;

This will depend on your [service manager](/docs/server/server-management/starting-and-stopping-mariadb.md). For example, on [systemd](/docs/server/server-management/starting-and-stopping-mariadb/systemd.md) systems, you may execute::

```bash
systemctl start mariadb
```

{% endstep %}

{% step %}

### Watch the MariaDB [error log](/docs/server/server-management/server-monitoring-logs/error-log.md)&#x20;

On the joiner node, verify that the node does not need to perform a [normal SSTs](/docs/galera-cluster/high-availability/state-snapshot-transfers-ssts-in-galera-cluster/introduction-to-state-snapshot-transfers-ssts.md) due to the manual SST.

```bash
tail -f /var/log/mysql/mysqld.log
```

{% endstep %}
{% endstepper %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mariadb.com/docs/galera-cluster/high-availability/state-snapshot-transfers-ssts-in-galera-cluster/manual-sst-of-galera-cluster-node-with-mariadb-backup.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
