为了有用,备份必须定期安排。在 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 所见的数据不会更改。(其他客户端对 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 也有一个选项可以刷新日志。数据目录中的 .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 语句”。