为了发挥作用,必须定期安排备份。可以使用多种工具在 MySQL 中完成完整备份(某个时间点的数据快照)。例如,MySQL 企业版备份 可以对整个实例执行 物理备份,并进行优化以最大程度地减少开销并在备份 InnoDB
数据文件时避免中断;mysqldump 提供在线 逻辑备份。本讨论使用 mysqldump。
假设我们在周日下午 1 点负载较低时使用以下命令对所有数据库中的所有 InnoDB
表进行完整备份
$> mysqldump --all-databases --source-data --single-transaction > backup_sunday_1_PM.sql
mysqldump 生成的 .sql
文件包含一组 SQL INSERT
语句,可用于在以后重新加载转储的表。
此备份操作在转储开始时获取所有表的全局读锁(使用 FLUSH TABLES WITH READ LOCK
)。获取此锁后,将读取二进制日志坐标并释放锁。如果在发出 FLUSH
语句时正在运行长时间更新语句,则备份操作可能会暂停,直到这些语句完成。之后,转储将变为无锁状态,并且不会干扰对表的读写。
前面假设要备份的表是 InnoDB
表,因此 --single-transaction
使用一致性读取并保证 mysqldump 看到的数据不会更改。(mysqldump 进程看不到其他客户端对 InnoDB
表所做的更改。)如果备份操作包括非事务性表,则一致性要求它们在备份期间不发生更改。例如,对于 mysql
数据库中的 MyISAM
表,在备份期间不得对 MySQL 帐户进行任何管理更改。
完整备份是必要的,但创建它们并不总是方便的。它们会生成大型备份文件,并且需要时间才能生成。它们不是最优的,因为每个连续的完整备份都包含所有数据,即使是自上次完整备份以来未更改的部分也是如此。更有效的方法是进行初始完整备份,然后进行增量备份。增量备份较小,并且生成所需的时间更少。折衷方案是,在恢复时,您不能仅通过重新加载完整备份来恢复数据。您还必须处理增量备份以恢复增量更改。
要进行增量备份,我们需要保存增量更改。在 MySQL 中,这些更改在二进制日志中表示,因此应始终使用 --log-bin
选项启动 MySQL 服务器以启用该日志。启用二进制日志记录后,服务器会在更新数据时将每个数据更改写入文件。查看运行了几天的 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 也有一个选项可以刷新日志。数据目录中的 .index
文件包含目录中所有 MySQL 二进制日志的列表。
MySQL 二进制日志对恢复很重要,因为它们构成增量备份集。如果您确保在进行完整备份时刷新日志,则之后创建的二进制日志文件将包含自备份以来所做的所有数据更改。让我们稍微修改一下之前的 mysqldump 命令,使其在完整备份时刷新 MySQL 二进制日志,并使转储文件包含新的当前二进制日志的名称
$> 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 点的完整备份和星期一下午 1 点之间的所有更改都写入 gbichot2-bin.000007
。此增量备份很重要,因此最好将其复制到安全的地方。(例如,将其备份到磁带或 DVD 上,或将其复制到另一台机器上。)在星期二下午 1 点,执行另一个 mysqladmin flush-logs 命令。星期一下午 1 点和星期二下午 1 点之间的所有更改都写入 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 语句”。