Percona XtraBackup is the industry-standard open-source tool for online, non-blocking hot backups of MySQL and MariaDB InnoDB databases. Unlike mysqldump, which produces a logical SQL dump and requires more time for large databases, XtraBackup performs a physical backup — copying InnoDB data files directly while MySQL is running, without acquiring table locks that would block writes. This makes XtraBackup the preferred backup solution for large databases (100 GB+) that cannot tolerate even a brief write lock during backup. XtraBackup also supports incremental backups (only changed pages since the last backup) and streaming backups directly to a remote server. This guide covers installing Percona XtraBackup 8.0 on RHEL 9, performing full and incremental backups, and restoring from backup.
Prerequisites
- MySQL 8 or MariaDB installed on RHEL 9
- A MySQL user with BACKUP_ADMIN and REPLICATION CLIENT privileges
Step 1 — Install Percona XtraBackup
# Add the Percona repository
dnf install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm
percona-release enable-only tools release
dnf install -y percona-xtrabackup-80
xtrabackup --version
Step 2 — Create a Dedicated Backup User
mysql -u root -p <<'SQL'
CREATE USER 'xtrabackup'@'localhost' IDENTIFIED BY 'XtraBackupPass123!';
GRANT BACKUP_ADMIN, PROCESS, RELOAD, REPLICATION CLIENT ON *.* TO 'xtrabackup'@'localhost';
GRANT SELECT ON performance_schema.* TO 'xtrabackup'@'localhost';
FLUSH PRIVILEGES;
SQL
Step 3 — Full Backup
# Create the backup directory
BACKUP_DIR="/var/backups/xtrabackup"
mkdir -p "$BACKUP_DIR/full-$(date +%Y%m%d)"
# Run the full backup
xtrabackup --backup
--user=xtrabackup
--password=XtraBackupPass123!
--target-dir="$BACKUP_DIR/full-$(date +%Y%m%d)"
# Prepare the backup (apply transaction logs — required before restore)
xtrabackup --prepare --target-dir="$BACKUP_DIR/full-$(date +%Y%m%d)"
Step 4 — Incremental Backup
# Incremental backup — only pages changed since the full backup
xtrabackup --backup
--user=xtrabackup
--password=XtraBackupPass123!
--target-dir="$BACKUP_DIR/incr-$(date +%Y%m%d)"
--incremental-basedir="$BACKUP_DIR/full-$(date +%Y%m%d --date='yesterday')"
# Prepare incremental backup (apply to the full backup)
xtrabackup --prepare --apply-log-only --target-dir="$BACKUP_DIR/full-20241201"
xtrabackup --prepare --target-dir="$BACKUP_DIR/full-20241201"
--incremental-dir="$BACKUP_DIR/incr-20241202"
Step 5 — Restore from Backup
# CAUTION: Restore overwrites the MySQL data directory
# Stop MySQL and clear data directory
systemctl stop mysqld
rm -rf /var/lib/mysql/*
# Copy back the prepared backup
xtrabackup --copy-back --target-dir="$BACKUP_DIR/full-20241201"
# Fix ownership
chown -R mysql:mysql /var/lib/mysql/
# Start MySQL
systemctl start mysqld
Step 6 — Stream Backup to Remote Server
# Stream compressed backup directly to a remote server via SSH
xtrabackup --backup --stream=xbstream --user=xtrabackup --password=XtraBackupPass123!
| gzip | ssh [email protected] "cat > /var/backups/mysql-$(date +%Y%m%d).xbstream.gz"
Conclusion
Percona XtraBackup on RHEL 9 provides non-blocking, hot MySQL backups that do not impact write performance. The prepare step applies the InnoDB transaction log to the backup before restore, ensuring a consistent point-in-time snapshot. For large databases (100 GB+), the combination of weekly full backups and daily incremental backups minimises both backup time and storage requirements while providing granular recovery points.
Next steps: How to Back Up MySQL with mysqldump on RHEL 9, How to Configure MySQL Primary-Replica Replication on RHEL 9, and How to Monitor MySQL with Prometheus on RHEL 9.