Prev: replication Next: scaling-mysql
Backups are important: think of the following:
Most cloud providers don’t provide backups of servers at all.
Think about the following:
Backups have lots of criteria. Snapshot-based backups like Percona XtraBackup and MySQL Enterprise Backup are the best.
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 backups (dumps) contains data in a format that MySQL can understand, like SQL.
Raw files are files as they exist on disk.
Logical Backups are normal sql files. That means they can be independent of storage engine, and helps avoid data corruption.
There are some cons:
But have some cons:
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.
You need to backup stuff that’s not just in tables:
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.
When you make a backup from a replica, GTID’s are recommended. This avoids having to save all the information about the replica.
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
.
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` (
int NOT NULL,
`a` PRIMARY KEY (`a`)
=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
) ENGINE/*!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:
Filesystem snapshots are a good way to make online backups. ZFS, LVM, SAN, and other filesystems can take snapshots for use.
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.
To get a consistent copy of all the files you want to backup:
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'
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 is a popular solution for backing up MySQL.
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...
xtrabackup --backup --target-dir=/backups/
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
Or with compression and streaming
xtrabackup --backup --compress --stream=xbstream > /backups/backup-
compressed.xbstream
You can also encrypt your backups.
xtrabackup --backup --encrypt=AES256 --encrypt-key-
file=/safe/key/location/encrypt.key --stream=xbstream > /backups/backup-
encrypted.xbstream
You can look at the --parallel
and
-compress-threads
options, or --rsync
to
optimize the file-copy process.
To recover from a backup:
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.
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.
To restore raw files, shut down MySQL, copy or move the files into place, and then restart.
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
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