MySQL 提供了多种备份方式,每种方式适用于不同的场景和需求。根据备份的粒度、速度、恢复时间和对数据库的影响,可以选择合适的备份策略。主要备份方式有三大类:逻辑备份(mysqldump),物理备份和二进制文件备份。
一、逻辑备份(Logical Backup)
逻辑备份是通过导出SQL语句或表结构和数据来实现的。它不直接复制物理文件,而是生成可以重新执行的SQL文件。逻辑备份的优点是易于理解和恢复,但通常比物理备份慢。
1、mysqldump工具
mysqldump是MySQL自带的命令行工具,用于导出数据库的表结构和数据。它可以生成完整的SQL文件,支持单个表、多个表或整个数据库的备份。
备份方式:
- 全量备份:备份整个数据库或多个数据库。
- 部分备份:可以只备份特定的表或数据库。
- 增量备份:可以通过--master-data和--single-transaction选项结合二进制日志进行增量备份。
mysqldump备份优点:
- 支持跨版本恢复。(如:8.0版本导出备份文件,可以在5.7版本Mysql上进行还原)
- 可以选择性地恢复部分数据。
- 生成的SQL文件易于理解和修改。
mysqldump备份缺点:
- 备份速度较慢,尤其是大数据库。
- 备份期间可能会锁定表(除非使用--single-transaction)。
- 恢复时间较长,因为需要重新执行SQL语句。
示例:(mysql命令,非sql语句)
(1)、备份所有数据库
java
mysqldump -u root -p --all-databases > all_databases.sql
运行结果:
会在当前目录下生成全量的sql文件。
查看如下:
包含所有的库,表和数据信息。
(2)、备份单个数据库
指定备份demo1数据库,输出到demo1.sql文件中。
java
mysqldump -u root -p demo1> demo1.sql
运行结果:
查看如下:
包含demo1库中的表和数据信息。
(3)、备份单个表
指定demo1数据库的employees表进行备份,输出到employees.sql文件中。
java
mysqldump -u root -p demo1 employees > employees.sql
运行结果:
查看如下:
(4)、使用压缩
使用压缩方式进行备份。
java
mysqldump -u root -p demo1 | gzip > demo1.sql.gz
如果备份文件非常大,且又需要频繁备份的场景。建议备份时启用压缩。
2、mysqlpump工具
mysqlpump是MySQL 5.7引入的一个新工具,类似于mysqldump,但性能更好,尤其是在处理大数据库时。它支持并行备份和更细粒度的控制。
mysqlpump优点:
- 支持并行备份,备份速度更快。
- 支持更多的并发操作。
- 可以选择性地备份存储过程、触发器等。
mysqlpump缺点:
- 不支持MySQL 5.6及之前版本。
- 恢复时间仍然较长。
示例:
(1)、备份全部数据库
java
mysqlpump -u root -p --all-databases > all_databases1.sql
运行结果:
(2)、备份单个数据库
备份demo1数据库,输出到demo1_1.sql文件中。
java
mysqlpump -u root -p demo1 > demo1_1.sql
运行结果:
(3)、并行备份多个数据库
备份demo1数据库和sys数据库到multiple_databases.sql文件中。
java
mysqlpump -u root -p --parallel-schemas=demo1,sys> multiple_databases.sql
运行结果:
二、物理备份(Physical Backup)
物理备份是直接复制数据库的物理文件(如.frm、.ibd等)。物理备份的速度通常比逻辑备份快,因为它是直接复制文件而不是生成SQL语句。物理备份可以分为热备份、温备份和冷备份。
1、冷备份(Cold Backup)
冷备份是指在数据库完全停止的情况下进行的备份。这种方式最简单,但会对业务造成停机影响。
步骤:
(1)、停止MySQL服务。
(2)、复制数据目录中的所有文件。
(3)、重启MySQL服务。
示例:
java
停止MySQL服务
sudo systemctl stop mysql
复制数据目录
cp -R /var/lib/mysql /backup/mysql_cold_backup
重启MySQL服务
sudo systemctl start mysql
优点:
- 简单易用。
- 备份速度快。
- 恢复速度快。
缺点:
- 需要停机,不适合生产环境。
- 无法进行增量备份。
2、温备份(Warm Backup)
温备份是指在数据库处于只读模式的情况下进行的备份。这种方式不会完全停止数据库,但会阻止写操作,因此对业务的影响较小。
步骤:
(1)、将数据库设置为只读模式。
(2)、复制数据目录中的所有文件。
(3)、恢复数据库的读写模式。
示例:
java
-- 设置只读模式
SET GLOBAL readonly = ON;
-- 复制数据目录
cp -R /var/lib/mysql /backup/mysql_warm_backup
-- 恢复读写模式
SET GLOBAL readonly = OFF;
优点:
- 不需要完全停机。
- 备份速度快。
- 恢复速度快。
缺点:
- 写操作会被阻止,可能影响业务。
- 无法进行增量备份。
3、热备份(Hot Backup)
热备份是指在数据库正常运行的情况下进行的备份。这种方式不会影响数据库的正常读写操作,适合生产环境。常见的热备份工具有Percona XtraBackup和MySQL Enterprise Backup。
(1)、Percona XtraBackup
Percona XtraBackup是一个开源的热备份工具,专门用于InnoDB和XtraDB存储引擎。它可以进行在线备份,并且支持增量备份和压缩。
特点:
- 支持热备份,不影响数据库的正常运行。
- 支持增量备份和全量备份。
- 支持压缩和流式备份。
- 支持备份加密。
- 支持并行备份和恢复。
示例:
java
安装Percona XtraBackup
sudo apt-get install percona-xtrabackup-80
进行全量备份
xtrabackup --user=root --password=your_password --backup --target-dir=/backup/full
进行增量备份
xtrabackup --user=root --password=your_password --backup --target-dir=/backup/incremental --incremental-basedir=/backup/full
恢复备份
xtrabackup --prepare --target-dir=/backup/full
xtrabackup --copy-back --target-dir=/backup/full
(2)、MySQL Enterprise Backup
MySQL Enterprise Backup是Oracle提供的商业备份工具,专为MySQL企业版设计。它提供了类似Percona XtraBackup的功能,但还有一些额外的企业级特性,如自动备份调度、备份验证等。
特点:
- 支持热备份,不影响数据库的正常运行。
- 支持增量备份和全量备份。
- 支持压缩和流式备份。
- 支持备份加密。
- 支持并行备份和恢复。
- 提供自动备份调度和备份验证。
优点:
- 支持热备份,不影响数据库的正常运行。
- 支持增量备份,节省存储空间。
- 备份速度快,恢复速度快。
- 适合大规模生产环境。
缺点:
- 需要购买 MySQL 企业版许可证。
三、二进制日志备份(Binary Log Backup)
二进制日志(binary log)记录了所有对数据库的更改操作(如INSERT、UPDATE、DELETE等)。通过备份二进制日志,可以在全量备份的基础上进行增量恢复,从而减少恢复时间。
步骤:
1、启用二进制日志。
2、定期备份二进制日志文件。
3、在恢复时,先恢复全量备份,再应用二进制日志中的更改恢复到指定时间点。
示例:
java
查看当前的二进制日志文件
mysql> SHOW MASTER LOGS;
查看日志的路径
SHOW VARIABLES LIKE 'datadir';
SHOW VARIABLES LIKE 'log_bin%';
备份二进制日志文件
cp /var/lib/mysql/mysql-bin. /backup/binlogs/
应用二进制日志进行恢复
mysqlbinlog /backup/binlogs/mysql-bin.000001 | mysql -u root -p
优点:
- 支持增量备份,节省存储空间。
- 可以进行精确的时间点恢复。
- 适合高可用性和灾难恢复场景。
缺点:
- 需要启用二进制日志,可能会增加I/O开销。
- 二进制日志文件较大,需要定期清理。
四、逻辑恢复
逻辑备份是通过mysqldump或mysqlpump等工具生成的SQL文件。恢复时,可以通过执行这些SQL文件来重新创建数据库和表结构,并插入数据。
1、使用mysqldump备份文件恢复
步骤:
(1)、导入SQL文件:将备份的SQL文件通过mysql命令行工具导入到目标数据库中。
(2)、指定数据库:如果备份的是单个数据库或多个数据库,确保在导入时指定正确的数据库名称。
示例:
(1)、恢复整个数据库
java
mysql -u root -p < all_databases.sql
运行结果:
所有的数据库都恢复到了备份文件生成的时间点。
(2)、恢复单个数据库:
恢复demo1数据库,执行demo1.sql文件
java
mysql -u root -p demo1 < demo1.sql
运行结果:
(3)、恢复单个表
恢复demo1数据库的employees表,执行employees.sql文件。
java
mysql -u root -p demo1 < employees.sql
运行结果:
优点:
- 支持跨版本恢复。
- 可以选择性地恢复部分数据(如单个表或存储过程)。
- 生成的SQL文件易于理解和修改。
缺点:
- 恢复速度较慢,尤其是大数据库。
- 如果备份文件较大,可能会占用较多内存和磁盘I/O。
- 需要重新执行SQL语句,可能导致锁表或阻塞其他操作。
2、使用mysqlpump备份文件恢复
mysqlpump是MySQL 5.7引入的一个新工具,支持并行备份和更细粒度的控制。恢复过程与mysqldump类似,几乎一样。
示例:
java
恢复整个数据库
mysql -u root -p < all_databases.sql
恢复单个数据库
指定恢复demo1数据库,执行demo1.sql文件
mysql -u root -p demo1 < demo1.sql
优点:
- 支持并行恢复,速度更快。
- 支持更多的并发操作。
- 可以选择性地恢复部分数据。
缺点:
- 不支持MySQL 5.6及以下版本。
五、物理恢复
物理备份是直接复制数据库的物理文件(如.frm、.ibd等)。物理备份的恢复速度通常比逻辑备份快,因为它是直接恢复文件而不是重新执行SQL语句。
1、冷备份的恢复
冷备份是在数据库完全停止的情况下进行的备份。恢复时,只需将备份的文件复制回原始位置,并重启MySQL服务。
步骤:
(1)、停止MySQL服务。
(2)、复制备份文件:将备份的数据目录复制回原始位置。
(3)、重启MySQL服务。
示例:
java
停止MySQL服务
sudo systemctl stop mysql
复制备份文件
cp -R /backup/mysql_cold_backup/ /var/lib/mysql/
重启MySQL服务
sudo systemctl start mysql
优点:
- 恢复速度快。
- 不需要重新执行SQL语句。
缺点:
- 需要停机,不适合生产环境。
- 无法进行增量恢复。
2、温备份的恢复
温备份是在数据库处于只读模式的情况下进行的备份。恢复时,只需将备份的文件复制回原始位置,并恢复数据库的读写模式。
步骤:
1、设置只读模式。
2、复制备份文件:将备份的数据目录复制回原始位置。
3、恢复读写模式。
示例:
java
-- 设置只读模式
SET GLOBAL readonly = ON;
-- 复制备份文件
cp -R /backup/mysql_warm_backup/ /var/lib/mysql/
-- 恢复读写模式
SET GLOBAL readonly = OFF;
优点:
- 不需要完全停机。
- 恢复速度快。
缺点:
- 写操作会被阻止,可能影响业务。
- 无法进行增量恢复。
3、热备份的恢复
热备份是在数据库正常运行的情况下进行的备份。常见的热备份工具有Percona XtraBackup和MySQL Enterprise Backup。恢复时,需要先准备备份文件,然后将其复制回原始位置。
(1)、使用Percona XtraBackup恢复
步骤:
1、准备备份文件:使用XtraBackup --prepare命令准备备份文件,确保其处于一致状态。
2、停止MySQL服务。
3、复制备份文件:将准备好的备份文件复制回原始位置。
4、重启MySQL服务。
示例:
java
准备全量备份
xtrabackup --prepare --target-dir=/backup/full
如果有增量备份,同时也要指定准备增量备份
xtrabackup --prepare --apply-log-only --target-dir=/backup/full --incremental-dir=/backup/incremental
停止MySQL服务
sudo systemctl stop mysql
删除现有数据目录
rm -rf /var/lib/mysql/
复制备份文件
xtrabackup --copy-back --target-dir=/backup/full
修改数据目录权限
chown -R mysql:mysql /var/lib/mysql
重启MySQL服务
sudo systemctl start mysql
优点:
- 支持热备份,不影响数据库的正常运行。
- 支持增量备份,节省存储空间。
- 恢复速度快。
缺点:
- 需要准备备份文件,增加了一步操作。
- 恢复过程中需要停止MySQL服务。
(2)、使用MySQL Enterprise Backup恢复
MySQL Enterprise Backup是Oracle提供的商业备份工具,恢复过程与Percona XtraBackup类似,但提供了更多企业级特性。
步骤:
1、准备备份文件:使用mysqlbackup --apply-log命令准备备份文件。
2、停止MySQL服务。
3、复制备份文件:将准备好的备份文件复制回原始位置。
4、重启MySQL服务。
示例:
java
准备全量备份
mysqlbackup --user=root --password=your_password --backup-dir=/backup/full --apply-log prepare
如果有增量备份,同时也要准备增量备份
mysqlbackup --user=root --password=your_password --backup-dir=/backup/full --incremental-backup-dir=/backup/incremental --apply-log prepare
停止MySQL服务
sudo systemctl stop mysql
删除现有数据目录
rm -rf /var/lib/mysql/
复制备份文件
mysqlbackup --user=root --password=your_password --backup-dir=/backup/full --copy-back
修改数据目录权限
chown -R mysql:mysql /var/lib/mysql
重启MySQL服务
sudo systemctl start mysql
优点:
- 支持热备份,不影响数据库的正常运行。
- 支持增量备份,节省存储空间。
- 恢复速度快。
- 提供自动备份调度和备份验证。
缺点:
- 需要购买MySQL企业版许可证。
六、二进制日志恢复
MySQL的二进制日志(Binary Log,简称binlog)记录了所有对数据库的更改操作(如INSERT、UPDATE、DELETE等)。通过二进制日志,可以实现增量备份、主从复制和时间点恢复。
1、什么是二进制日志?
二进制日志是MySQL中的一种日志文件,记录了所有对数据库的更改操作。它以二进制格式存储,因此不能直接阅读,但可以通过工具解析。
二进制日志的主要用途包括:
- 主从复制:主库将二进制日志发送给从库,从库根据日志重放这些操作,保持与主库同步。
- 增量备份:在全量备份的基础上,使用二进制日志进行增量备份,减少备份时间和存储空间。
- 时间点恢复:通过二进制日志,可以在某个特定的时间点恢复数据,避免不必要的数据丢失。
2、启用二进制日志
要使用二进制日志,首先需要在MySQL配置文件中启用它。编辑/etc/my.cnf或/etc/mysql/my.cnf文件,添加或修改以下配置项。
示例:
java
[mysqld]
启用二进制日志
log_bin=mysql-bin
设置二进制日志的格式(STATEMENT、ROW 或 MIXED)
binlog_format=ROW
设置二进制日志的过期天数(可选)
expire_logs_days=7
设置二进制日志的最大文件大小(可选)
max_binlog_size=100M
设置唯一的服务器 ID(用于主从复制)
server_id=1
解释:
- log_bin:指定二进制日志的文件名前缀。默认情况下,MySQL会将日志文件保存在数据目录中(通常是/var/lib/mysql/)。
- binlog_format:设置二进制日志的格式。常见的格式有:
- STATEMENT:记录SQL语句。
- ROW:记录每一行的变化(推荐使用,尤其是对于InnoDB表)。
- MIXED:混合模式,MySQL会根据情况自动选择STATEMENT或ROW。
- expire_logs_days:设置二进制日志的保留天数。超过这个天数的日志将被自动删除。
- max_binlog_size:设置单个二进制日志文件的最大大小。当达到这个大小时,MySQL会创建一个新的日志文件。
- server_id:设置唯一的服务器ID,用于主从复制。
重启MySQL服务:
修改配置文件后,重启MySQL服务以使配置生效:
java
sudo systemctl restart mysql
3、查看二进制日志文件
启用二进制日志后,MySQL会在数据目录中生成一系列以mysql-bin.000001、mysql-bin.000002等命名的文件。
相关示例:
(1)、查看二进制日志文件列表
java
SHOW BINARY LOGS;
输出示例:
(2)、查看当前正在使用的二进制日志文件
java
SHOW MASTER STATUS;
输出示例:
解释:
- File:当前正在使用的二进制日志文件。
- Position:当前日志文件中的写入位置。
4、备份二进制日志
为了确保数据的安全性,建议定期备份二进制日志。
常见的备份方法:
(1)、手动备份
你可以直接复制二进制日志文件到备份目录中。由于二进制日志文件是追加写入的,因此可以安全地复制它们,而不会影响MySQL的正常运行。
示例:
java
创建备份目录
mkdir -p /backup/binlogs
复制二进制日志文件
cp /var/lib/mysql/mysql-bin. /backup/binlogs/
(2)、mysqlbinlog工具备份
mysqlbinlog是MySQL提供的一个工具,用于解析和导出二进制日志文件。你可以使用它将二进制日志转换为SQL文件,便于备份和恢复。
示例:
1、将所有二进制日志导出为SQL文件
java
mysqlbinlog /var/lib/mysql/mysql-bin.000001 > /backup/binlogs/mysql-bin.000001.sql
mysqlbinlog /var/lib/mysql/mysql-bin.000002 > /backup/binlogs/mysql-bin.000002.sql
2、指定时间范围的备份
java
mysqlbinlog --start-datetime="2023-10-01 00:00:00" --stop-datetime="2023-10-02 00:00:00" /var/lib/mysql/mysql-bin.000001 > /backup/binlogs/mysql-bin.000001.sql
解释:
- --start-datetime和--stop-datetime:指定导出的时间范围。
3、指定行数的备份
java
mysqlbinlog --start-position=1234 --stop-position=5678 /var/lib/mysql/mysql-bin.000001 > /backup/binlogs/mysql-bin.000001.sql
解释:
- --start-position和--stop-position:指定导出的位置范围。
4、从远程服务器进行复制备份
java
mysqlbinlog --read-from-remote-server --host=192.168.1.100 --user=root --password=your_password /var/lib/mysql/mysql-bin.000001 > /backup/binlogs/mysql-bin.000001.sql
解释:
- --read-from-remote-server:从远程服务器读取二进制日志(适用于主从复制环境)。
5、自动化备份
为了实现自动化的二进制日志备份,可以编写一个脚本并结合cron定时任务来定期执行备份。
以下是一个简单的Shell脚本示例:
第一步:编写自动化脚本(backup_binlogs.sh),如下:
java
#!/bin/bash
# 配置变量
BACKUP_DIR="/backup/binlogs"
DATE=$(date +%Y%m%d_%H%M%S)
MYSQL_USER="root"
MYSQL_PASSWORD="your_password"
# 创建备份目录(如果不存在)
mkdir -p $BACKUP_DIR
# 获取当前的二进制日志文件列表
BINARY_LOGS=$(mysql -u $MYSQL_USER -p$MYSQL_PASSWORD -e "SHOW BINARY LOGS" | awk 'NR>1 {print $1}')
# 备份每个二进制日志文件
for LOG in $BINARY_LOGS; do
FILENAME="${BACKUP_DIR}/${LOG}_${DATE}.sql.gz"
echo "Backing up binary log: $LOG to $FILENAME"
# 使用 mysqlbinlog 导出并压缩日志文件
mysqlbinlog -u $MYSQL_USER -p$MYSQL_PASSWORD /var/lib/mysql/$LOG | gzip > $FILENAME
if [ $? -eq 0 ]; then
echo "Backup of $LOG completed successfully."
else
echo "Backup of $LOG failed."
fi
done
# 清理旧备份(保留最近7天的备份)
find $BACKUP_DIR -type f -name "*.sql.gz" -mtime +7 -exec rm {} \;
第二步:设置定时任务
(1)、打开crontab编辑器:
java
crontab -e
(2)、添加以下行,每天凌晨2点执行备份脚本:
java
0 2 * * * /path/to/backup_binlogs.sh >> /var/log/binlog_backup.log 2>&1
(3)、保存并退出。
解释:
- 0 2 * * * :表示每天凌晨2点执行。
- /path/to/backup.sh:替换为你的备份脚本的实际路径。
-
/var/log/mysql_backup.log 2>&1:将输出和错误日志重定向到指定的日志文件。
6、清理二进制日志
随着时间的推移,二进制日志文件会逐渐增多,占用大量磁盘空间。因此,定期清理不再需要的二进制日志是非常重要的。
你可以通过以下方式清理二进制日志:
(1)、自动清理
通过配置expire_logs_days参数,可以让MySQL自动清理超过指定天数的二进制日志。例如,设置expire_logs_days=7,表示保留最近7天的二进制日志,超过7天的日志将被自动删除。
(2)、手动清理
你可以使用PURGE BINARY LOGS命令手动清理二进制日志。
常见的清理方式:
- 按文件名清理:删除指定文件名之前的二进制日志。
sql示例:
java
PURGE BINARY LOGS TO 'mysql-bin.000010';
- 按日期清理:删除指定日期之前的二进制日志。
sql示例:
java
PURGE BINARY LOGS BEFORE '2023-10-01 00:00:00';
- 清空所有二进制日志:删除所有二进制日志并重置日志编号。请注意,这会影响主从复制,谨慎使用。
sql示例:
java
RESET MASTER;
7、使用二进制日志进行恢复
二进制日志可以用于增量恢复,尤其是在全量备份的基础上。通过应用二进制日志中的操作,可以将数据库恢复到某个特定的时间点。结合恢复全量备份和二进制日志恢复。
示例:
假设你已经有一个过去的全量备份,并且希望恢复到某个时间点。
java
1、恢复全量备份:首先恢复最近的全量备份。
mysql -u root -p < full_backup.sql
2、应用二进制日志:使用mysqlbinlog解析并应用二进制日志文件。你可以根据需要指定时间范围或位置范围。
mysqlbinlog --start-datetime="2023-10-01 00:00:00" --stop-datetime="2023-10-02 10:00:00" /var/lib/mysql/mysql-bin.000001 | mysql -u root -p
解释:
为什么要先进行全量备份的恢复呢?
全量备份是数据库的一个完整副本,包含了所有表、索引、视图等对象的数据。它是数据库恢复的基础,提供了恢复过程中的"起点"。二进制日志记录了自全量备份之后的所有数据库更改操作。如果你有的只是二进制文件没有之前的备份文件,那么恢复是无法进行的。简单说就是二进制文件的起点行不知道是哪一句增删改的语句,甚至当前的数据库中表都不存在了。
过程推理说明:
假设2025年的1月4日15点30分,你不小心删除了某张重要表的数据。
第一步:(假设每天的0点都进行全量的数据库备份)
你要先找到1月4日0点的全量备份文件。执行恢复此文件,将数据库还原到1月4日0点的状态。
第二步:
找到正在执行的binlog日志文件(不确定可以指定最近的两个),指定开始时间为1月4日0点,结束时间会1月4日15点0分(误删表的前一小段时间点)。
这样就相当于在1月4日0点当时数据库的基础上,重新执行了0点到15点这段时间内的所有增删改的语句,从而实现了故障恢复的效果。
8、监控二进制日志
为了确保二进制日志的健康状态,建议定期监控其使用情况。你可以使用以下查询来获取二进制日志的相关信息:
查看二进制日志的状态:
java
SHOW MASTER STATUS;
运行结果:
查看二进制日志的文件列表:
java
SHOW BINARY LOGS;
运行结果:
查看二进制日志的事件:
java
SHOW BINLOG EVENTS IN 'mysql-bin.000001';
运行结果:
监控二进制日志的大小:
java
SELECT
*
FROM
performance_schema.file_summary_by_instance
WHERE
file_name LIKE '%mysql-bin%';
运行结果:
乘风破浪会有时,直挂云帆济沧海!!!