Backup and Recovery
Prev: replication Next: scaling-mysql
Backups are important: think of the following:
- Security (access to the backups, privileges to restore data, encryption)
- Where to store the backups (different disk, server, or offsite)
- Retention policies
- Storage solutions
- Storage formats
- Monitoring backups
- Backup capabilities built into storage layers
Why Backups?
- Disaster recovery
- People changing their minds
- Auditing
- Testing
Most cloud providers don’t provide backups of servers at all.
Defining Recovery Requirements
Think about the following:
- How much data can you lose without serious consequences?
- How fast does recovery have to be? How much availability loss will your customers tolerate?
- What do you need to recover? A table? A database? A server?
Designing a MySQL Backup Solution
Backups have lots of criteria. Snapshot-based backups like Percona XtraBackup and MySQL Enterprise Backup are the best.
Online or Offline Backups?
If you can get away with it, shutting down the server to writes makes backups easy.
If your application has less traffic during some times, this is a good time to run backups while online.
Logical or Raw Backups?
Logical backups (dumps) contains data in a format that MySQL can understand, like SQL.
Raw files are files as they exist on disk.
Logical Backups
Logical Backups are normal sql files. That means they can be independent of storage engine, and helps avoid data corruption.
There are some cons:
- The server spends more CPU time generating them
- Dumping and restoring data can sometimes be non-deterministic
- Restoring from a logical backup requires MySQL to load and interpret statements, which is very slow.
Raw backups
- Raw backups are generally cheaper to generate
- Faster to backup
But have some cons:
- Are often far larger than logical backups
- Raw backups might run into architecture specific problems.
Raw backups are generally easier and more efficient, but should not be relied upon for legal requirements.
You should try to dump in both formats.
What to Back Up
You need to backup stuff that’s not just in tables:
- Binlogs, and InnoDB transaction logs
- Code (like triggers and stored procedures)
- Server configuration
- Operating system files, like cron jobs and administrative scripts
Incremental Backups
Incremental backups are good in the case you can’t backup the whole database. First, take a whole snapshot, then incrementally take snapshot changes from that time.
Replication
When you make a backup from a replica, GTID’s are recommended. This avoids having to save all the information about the replica.
Managing and Backing Up Binary Logs
MySQL will fill up your disk with binary logs. You’ll need to decide on a log-based expiration policy to keep MySQL from filling your disk with binary logs.
MySQL can purge binlogs automatically with binlog_expire_logs_seconds
.
Backup and Recovery Tools
- MySQL Enterprise Tools (Oracle provided)
- Percona XtraBackup (open sourcing and free)
- mydumper (multi-threaded backups)
- mysqldump (comes with MySQL)
Logical SQL Backups
Mysqldump creates logical dumps by default:
You can run mysqldump
like so:
mysqldump test t1
-- [Version and host comments]
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-- [More version-specific comments to save options for restore]
--
-- Table structure for table `t1`
--
DROP TABLE IF EXISTS `t1`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `t1` (
`a` int NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `t1`
--
LOCK TABLES `t1` WRITE;
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
INSERT INTO `t1` VALUES (1);
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-- [More option restoration]
There are some problems with logical backups:
- Schema and data stored together.
- Huge SQL Statements
- A single huge file
- Logical backups are expensive
Filesystem Snapshots
Filesystem snapshots are a good way to make online backups. ZFS, LVM, SAN, and other filesystems can take snapshots for use.
How LVM snapshots work
LVM uses copy-on-write to create a snapshot. It’s a logical copy of an entire volume at an instant in time. This works like MVCC, except only keeping one old version of the data.
Prerequisites and configuration
To get a consistent copy of all the files you want to backup:
- All InnoDB files must be on a single logical volume.
- If you need to backup table definitions, the MySQL data directory must be on the same Logical volume.
- The volume group must have enough free space to create the snapshot.
LVM has the concept of a volume group, which contains one or more
logical volumes. You can query this with vgs
.
$ vgs
VG #PV #LV #SN Attr VSize VFree
vg 1 4 0 wz--n- 534.18G 249.18G
The lvs
command shows the logical volumes on the system.
lvs
LV VG Attr LSize Origin Snap% Move Log Copy%
home vg -wi-ao 40.00G
mysql vg -wi-ao 225.00G
tmp vg -wi-ao 10.00G
var vg -wi-ao 10.00G
The MySQL volume has 225GB of space, and it is named /dev/vg/mysql
.
To create, mount, and remove an LVM snapshot:
You can use the lvcreate
command to create a logical backup,
backup_mysql
.
lvcreate --size 16G --snapshot --name backup_mysql /dev/vg/mysql
Logical volume "backup_mysql" created
You can watch its status with nagios:
watch 'lvs | grep backup'
Lock-free InnoDB backups with LVM snapshots
To take a backup on MySQL 8+, while MySQL is running, take a snapshot, mount the snapshot, and then copy the files to your backup location.
Calculate how much data your server writes by use vmstat
or iostat
.
Assume it takes an hour to copy the snapshot to another server. You will need 1/2 _ 10MB _ 3600 or about 18GB of space for the snapshot.
Percona XtraBackup
Percona XtraBackup is a popular solution for backing up MySQL.
How XtraBackup works
It can be used like so:
xtrabackup --backup --target-dir=/backups/
xtrabackup version 8.0.25-17 based on MySQL server 8.0.25 Linux (x86_64)
(revision id: d27028b)
Using server version 8.0.25-15
210821 17:01:40 Executing LOCK TABLES FOR BACKUP...
Example usage
Basic Backup to directory
xtrabackup --backup --target-dir=/backups/
Streaming backup
This command does streaming backups to stdout.
xtrabackup --backup --stream=xbstream > /backups/backup.xbstream
You could add the timestamp too:
xtrabackup --backup --stream=xbstream > /backups/backup-$(date +%F).xbstream
Backup with compression
Or with compression and streaming
xtrabackup --backup --compress --stream=xbstream > /backups/backup-
compressed.xbstream
Backup with encryption
You can also encrypt your backups.
xtrabackup --backup --encrypt=AES256 --encrypt-key-
file=/safe/key/location/encrypt.key --stream=xbstream > /backups/backup-
encrypted.xbstream
Other important flags
You can look at the --parallel
and -compress-threads
options, or
--rsync
to optimize the file-copy process.
Recovering from a Backup
To recover from a backup:
- Stop the MySQL server.
- Take notes on the server’s configuration and file permissions.
- Move the data from the backup into the MySQL data directory.
- Make configuration changes.
- Change file permissions.
- Restart the server with limited access, and wait for it to start fully.
- Reload logical backup files.
- Examine and replay binary logs.
- Verify what you’ve restored.
- Restart the server with full access.
Make sure that MySQL is inaccessible to everything but the recovery
process: start MySQL with the --skip-networking
and
--socket=/tmp/mysql_recover.sock
options.
Restoring Logical Backups
If you have a logical backup, you can pass it to mysql directly:
mysql < sakila-backup.sql
If you compressed the backup, you can decompress and load in a single operation:
gunzip -c sakila-backup.sql.gz | mysql
Or for a single table:
grep 'INSERT INTO `actor`' sakila-backup.sql | mysql sakila
Or if the file is compressed:
gunzip -c sakila-backup.sql.gz | grep 'INSERT INTO `actor`'| mysql sakila
Try to backup into tables and data to avoid having to sed
a huge dump
file.
Restoring Raw Files from Snapshot
To restore raw files, shut down MySQL, copy or move the files into place, and then restart.
Restoring with Percona XtraBackup
If you used a streaming backup, unpack the xbstream
file.
xbstream -x < backup.xbstream
For a compressed file, pass --decompress
and for an encrypted file,
pass --decrypt
with --encrypt-key-file
.
xbstream -x --decompress < backup-compressed.xbstream
xbstream -x --decrypt --encrypt-key-file=/safe/key/location/encrypt.key
< backup-encrypted.xbstream
Once complete, you can prepare the files:
xtrabackup --prepare --target-dir=/restore
And then restore:
xtrabackup --move-back --target-dir=/restore
Starting MySQL After Restoring Raw Files
Now that you’ve restored the backup, pay attention to unix permissions, otherwise MySQL might not start.
Also, watch the MySQL error log while the server starts.
tail -f /var/log/mysql/mysql.err
You should run SHOW TABLE STATUS
in each database, and check the error
log in newer versions.
Prev: replication Next: scaling-mysql