要使备份有用,必须定期计划备份。在 MySQL 中,可以使用多种工具来执行完整备份(在某个时间点的数据快照)。例如,MySQL 企业备份可以对整个实例执行物理备份,以最小化开销和避免备份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
)。在获取锁后,读取二进制日志坐标,然后释放锁。如果在发出FLUSH
语句时有长时间更新语句正在运行,备份操作可能会等待这些语句完成。然后,dump 变得无锁,不会干扰表格的读取和写入。
之前假设要备份的表格是InnoDB表格,因此--single-transaction
使用一致的读取,确保mysqldump看到的数据不变。(其他客户端对InnoDB表格的更改不会被mysqldump进程看到。)如果备份操作包括非事务表格,需要确保它们在备份期间不变。例如,对于MyISAM表格在mysql数据库中,必须在备份期间不进行 MySQL 账户的管理更改。
完整备份是必要的,但是创建它们并不总是方便的。它们生成大型备份文件,并且需要时间来生成。它们不是最优的,因为每个连续的完整备份都包括所有数据,即使自上一个完整备份以来没有改变的部分。更高效的方法是创建初始完整备份,然后创建增量备份。增量备份更小,生成时间也更短。 tradeoff 是,在恢复时间,不能仅通过重新加载完整备份来恢复数据。您还必须处理增量备份以恢复增量更改。
要创建增量备份,我们需要保存增量更改。在 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 语句”。