mysqldump提供在线逻辑备份的功能。以下讨论使用mysqldump进行备份的策略。
假设我们使用以下命令在周日下午1点(此时负载较低)对所有数据库中的所有InnoDB表进行全备份:
$> mysqldump --all-databases --master-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 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 --master-data=2 \--all-databases > backup_sunday_1_PM.sql
执行此命令后,数据目录中将包含一个新的二进制日志文件,gbichot2-bin.000007,因为--flush-logs选项导致服务器刷新其日志。--master-data选项使mysqldump将二进制日志信息写入其输出,因此生成的.sql转储文件包括这些行:
-- Position to start replication or point-in-time recovery from
-- CHANGE MASTER TO MASTER_LOG_FILE='gbichot2-bin.000007',MASTER_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 --master-data=2 \--all-databases --delete-master-logs > backup_sunday_1_PM.sql
注意
使用mysqldump --delete-master-logs删除MySQL二进制日志可能会有风险,如果你的服务器是复制源服务器,因为副本可能还没有完全处理二进制日志的内容。在删除MySQL二进制日志之前应验证的事项,请参见“PURGE BINARY LOGS Statement”部分的说明。