上一节,第 9.5.1 节,「使用二进制日志进行点时恢复」,解释了使用二进制日志进行点时恢复的总体想法。该节详细解释了操作过程,并提供了一个示例。
例如,假设在 2020 年 3 月 11 日 20:06:00 左右执行了一条删除表的 SQL 语句。你可以执行点时恢复,以恢复服务器到删除表之前的状态。以下是一些示例步骤来实现这一点:
-
恢复最后一个在感兴趣点之前创建的完整备份(称为
tp
,在我们的示例中为 2020 年 3 月 11 日 20:06:00)。完成后,记录恢复的二进制日志位置,以便后续使用,并重新启动服务器。Note虽然 InnoDB 在恢复和服务器重新启动后也会显示最后一个二进制日志位置,但这 不是 获得恢复结束日志位置的可靠方法,因为可能存在 DDL 事件和非 InnoDB 更改,这些更改发生在显示的位置之后。你的备份和恢复工具应该提供最后一个二进制日志位置:例如,如果你使用 mysqlbinlog 完成该任务,请检查二进制日志回放的停止位置;如果你使用 MySQL Enterprise Backup,最后一个二进制日志位置已经保存在你的备份中。请参阅 点时恢复。
-
找到对应于你想要恢复数据库的点时的精确二进制日志事件位置。在我们的示例中,因为我们知道表删除发生的时间(
tp
),我们可以通过使用 mysqlbinlog 实用程序检查该时间附近的日志内容,来找到日志位置。使用--start-datetime
和--stop-datetime
选项指定一个短时间段 autourtp
,然后在输出中查找事件。$> mysqlbinlog --start-datetime="2020-03-11 20:05:00" \ --stop-datetime="2020-03-11 20:08:00" --verbose \ /var/lib/mysql/bin.123456 | grep -C 15 "DROP TABLE" /*!80014 SET @@session.original_server_version=80019*//*!*/; /*!80014 SET @@session.immediate_server_version=80019*//*!*/; SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; # at 232 #200311 20:06:20 server id 1 end_log_pos 355 CRC32 0x2fc1e5ea Query thread_id=16 exec_time=0 error_code=0 SET TIMESTAMP=1583971580/*!*/; SET @@session.pseudo_thread_id=16/*!*/; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/; SET @@session.sql_mode=1168113696/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C utf8mb4 *//*!*/; SET @@session.character_set_client=255,@@session.collation_connection=255,@@session.collation_server=255/*!*/; SET @@session.lc_time_names=0/*!*/; SET @@session.collation_database=DEFAULT/*!*/; /*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/; DROP TABLE `pets`.`cats` /* generated by server */ /*!*/; # at 355 #200311 20:07:48 server id 1 end_log_pos 434 CRC32 0x123d65df Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=no original_committed_timestamp=1583971668462467 immediate_commit_timestamp=1583971668462467 transaction_length=473 # original_commit_timestamp=1583971668462467 (2020-03-11 20:07:48.462467 EDT) # immediate_commit_timestamp=1583971668462467 (2020-03-11 20:07:48.462467 EDT) /*!80001 SET @@session.original_commit_timestamp=1583971668462467*//*!*/; /*!80014 SET @@session.original_server_version=80019*//*!*/; /*!80014 SET @@session.immediate_server_version=80019*//*!*/; SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; # at 434 #200311 20:07:48 server id 1 end_log_pos 828 CRC32 0x57fac9ac Query thread_id=16 exec_time=0 error_code=0 Xid = 217 use `pets`/*!*/; SET TIMESTAMP=1583971668/*!*/; /*!80013 SET @@session.sql_require_primary_key=0*//*!*/; CREATE TABLE dogs
从 mysqlbinlog 的输出中,我们可以找到
DROP TABLE `pets`.`cats`
语句,它位于二进制日志的某个段落中,介于# at 232
和# at 355
之间,这意味着该语句发生在日志位置 232 之后,日志位置 355 是在DROP TABLE
语句之后。Note仅使用
--start-datetime
和--stop-datetime
选项来帮助你找到实际事件的位置。不要使用这两个选项来指定要应用的二进制日志段落范围:这样做可能会错过二进制日志事件。相反,使用--start-position
和--stop-position
。 -
将二进制日志文件中的事件应用于服务器,从你在步骤 1 中找到的日志位置开始(假设为 155),直到你在步骤 2 中找到的日志位置(在你感兴趣的点之前):
$> mysqlbinlog --start-position=155 --stop-position=232 /var/lib/mysql/bin.123456 \ | mysql -u root -p
该命令恢复了从起始位置到停止位置之间的所有事务。由于 mysqlbinlog 的输出包括每个记录的
SET TIMESTAMP
语句,因此恢复的数据和相关的 MySQL 日志反映了原始事务执行的时间。现在,你的数据库已经恢复到了感兴趣的点时
tp
,就在删除表pets.cats
之前。 -
在已经完成的点时恢复之外,如果您还想重新执行您感兴趣的点后的所有语句,请再次使用 mysqlbinlog 将所有事件应用于服务器,自点
tp
之后。我们在步骤 2 中注意到,跳过语句后的日志位于位置 355;我们可以使用--start-position
选项,以便包括该位置后的所有语句:$> mysqlbinlog --start-position=355 /var/lib/mysql/bin.123456 \ | mysql -u root -p
您的数据库已经恢复到二进制日志文件中记录的最新语句,但跳过了所选事件。