9.3.1 建立备份策略
为了有用,备份必须定期进行。MySQL 可以使用多种工具建立全量备份(数据的某个时间点快照)。例如,MySQL Enterprise Backup 可以对整个实例进行 物理备份,优化减少 overhead 和避免在备份 InnoDB
数据文件时的中断;mysqldump 提供在线 逻辑备份。以下讨论使用 mysqldump。
假设我们在星期天下午1点,负载低时,对所有数据库中的 InnoDB
表进行全量备份:
$> mysqldump --all-databases --source-data --single-transaction > backup_sunday_1_PM.sql
由 mysqldump 产生的 .sql
文件包含了一组 SQL INSERT
语句,可以在后续时间重新加载备份表。
这个备份操作在开始dump时,获取所有表的全局读锁(使用FLUSH TABLES WITH READ LOCK
)。一旦获取了该锁,binary log坐标就被读取,然后释放锁。如果在发出FLUSH
语句时,有长时间更新的语句正在运行,备份操作可能会等待这些语句完成。然后,dump就不再锁定表,并且不会干扰读写操作。
之前假设要备份的是InnoDB
表,所以--single-transaction
使用一致的读取方式,确保mysqldump不改变数据。(InnoDB
表中的更改由其他客户端进行,不会被mysqldump进程看到。如果备份操作包括非事务表,要求这些表在备份期间不发生变化。例如,对于mysql
数据库中的MyISAM
表,在备份期间不能进行MySQL账户的管理更改。
全量备份是必要的,但是创建它们不总是方便的。它们生成了大文件,需要花费时间来生成。它们不是最优的,因为每个连续的全量备份都包含了自上一个全量备份以来所有数据,即使部分数据没有变化。更高效的是首先创建一个全量备份,然后创建增量备份。增量备份较小,生产时间也短。但是,在恢复时,你不能只靠重新加载全量备份来恢复数据,还需要处理增量备份以恢复增量变更。
为了创建增量备份,我们需要保存增量变更。在 MySQL 中,这些变更在二进制日志中表示,所以 MySQL 服务器应该总是使用--log-bin
选项来启用该日志。启用二进制日志后,服务器在更新数据时将每个数据变更写入文件。在一个已经运行了几天的 MySQL 服务器的数据目录中,我们找到这些 MySQL 二进制日志文件:
-rw-rw---- 1 guilhem guilhem 1277324 Nov 10 23:59 gbichot2-bin.000001
-rw-rw---- 1 guilhem guilhem 4 Nov 10 23:59 gbichot2-bin.000002
-rw-rw---- 1 guilhem guilhem 79 Nov 11 11:06 gbichot2-bin.000003
-rw-rw---- 1 guilhem guilhem 508 Nov 11 11:08 gbichot2-bin.000004
-rw-rw---- 1 guilhem guilhem 220047446 Nov 12 16:47 gbichot2-bin.000005
-rw-rw---- 1 guilhem guilhem 998412 Nov 14 10:08 gbichot2-bin.000006
-rw-rw---- 1 guilhem guilhem 361 Nov 14 10:07 gbichot2-bin.index
每次重启,MySQL 服务器都会创建一个新的二进制日志文件,使用序列中的下一个数字。服务器正在运行时,您也可以手动关闭当前的二进制日志文件,并开始一个新文件,通过执行FLUSH LOGS
SQL 语句或使用mysqladmin flush-logs 命令。 mysqldump 也有一个flush日志的选项。数据目录中的.index
文件包含该目录中的所有 MySQL 二进制日志列表。
MySQL 二进制日志对于恢复非常重要,因为它们组成了增量备份集。如果您在做全备时确保刷新了日志,那么创建后的二进制日志文件中包含自备以来所有数据变化。让我们修改之前的mysqldump 命令,使其在全备时刷新 MySQL 二进制日志,并使得dump 文件包含新当前二进制日志的名称:
$> mysqldump --single-transaction --flush-logs --source-data=2 \
--all-databases > backup_sunday_1_PM.sql
执行该命令后,数据目录中包含一个新的二进制日志文件,gbichot2-bin.000007
--flush-logs
选项导致服务器刷新日志。 --source-data
选项导致mysqldump将二进制日志信息写入输出,故生成的.sql
备份文件中包含这些行:
-- Position to start replication or point-in-time recovery from
-- CHANGE REPLICATION SOURCE TO SOURCE_LOG_FILE='gbichot2-bin.000007',SOURCE_LOG_POS=4;
因为mysqldump命令执行了完整备份,那些行表示两个意思:
-
备份文件包含在
gbichot2-bin.000007
二进制日志文件或更高版本之前的所有变更。 -
备份后所有数据变更都没有出现在备份文件中,但却出现在
gbichot2-bin.000007
二进制日志文件或更高版本中。
星期一下午1点,我们可以通过刷新日志来创建增量备份,例如执行mysqladmin flush-logs命令创建gbichot2-bin.000008
。从星期日下午1点到星期一下午的所有更改都写入了gbichot2-bin.000007
。这个增量备份很重要,所以应该将其复制到安全的地方(例如,备份到磁带或DVD,或者复制到另一个机器上)。星期二下午1点,执行另一个mysqladmin flush-logs命令。从星期一下午到星期二下午的所有更改都写入了gbichot2-bin.000008
(也应该将其复制到安全的地方)。
MySQL二进制日志占用磁盘空间。为了释放空间,时不时地清除它们。一个方法是删除不再需要的二进制日志,例如,当我们做了全备份时:
$> mysqldump --single-transaction --flush-logs --source-data=2 \
--all-databases --delete-source-logs > backup_sunday_1_PM.sql
使用mysqldump--delete-source-logs
删除 MySQL 二进制日志可能会危险,如果您的服务器是复制源服务器,因为副本可能还没有完全处理二进制日志的内容。PURGE BINARY LOGS 语句的描述解释了在删除 MySQL 二进制日志前需要验证什么。请参阅第15.4.1.1节,“PURGE BINARY LOGS 语句”。