MySQL 8.0 参考手册  / 第 7 章备份与恢复  / 7.5 时间点(增量)恢复  /  7.5.2 使用事件位置的时间点恢复

7.5.2 使用事件位置的时间点恢复

最后一节, 第 7.5.1 节,“使用二进制日志进行时间点恢复”,解释了使用二进制日志执行时间点恢复的一般思路。本节通过示例详细说明操作。

举个例子,假设2020年5月27日13:00:00左右,执行了一条删除表的SQL语句。您可以执行时间点恢复以将服务器恢复到表删除之前的状态。这些是实现该目标的一些示例步骤:

  1. 恢复在感兴趣的时间点之前创建的最后一个完整备份(在我们的示例中称之为 2020 年 5 月 27 日 13:00:00)。完成后,记下您已将服务器恢复到的二进制日志位置以备后用,然后重新启动服务器。 tp

    笔记

    虽然在恢复和服务器重启后 InnoDB 也会显示恢复的最后一个二进制日志位置,但这不是获取恢复结束日志位置的可靠方法,因为可能发生了 DDL 事件和非 InnoDB 更改在显示位置反映的时间之后。您的备份和还原工具应该为您提供最后一个二进制日志位置以供您恢复:例如,如果您使用的是mysqlbinlog 对于任务,检查二进制日志重放的停止位置;如果您使用的是 MySQL Enterprise Backup,则最后一个二进制日志位置已保存在您的备份中。请参阅 时间点恢复

  2. 找到与要将数据库还原到的时间点对应的精确二进制日志事件位置。在我们的示例中,假设我们知道表删除发生的大致时间 ( ),我们可以通过使用mysqlbinlog实用程序检查该时间附近的日志内容来找到日志位置。使用和 选项指定围绕 的短时间段 ,然后在输出中查找事件。例如: tp--start-datetime--stop-datetimetp

    $> mysqlbinlog   --start-datetime="2020-05-27 12:59:00" --stop-datetime="2020-05-27 13:06:00" \
      --verbose /var/lib/mysql/bin.123456 | grep -C 12 "DROP TABLE"
    # at 1868
    #200527 13:00:30 server id 2  end_log_pos 1985 CRC32 0x8b894489 	Query	thread_id=8	exec_time=0	error_code=0
    use `pets`/*!*/;
    SET TIMESTAMP=1590598830/*!*/;
    SET @@session.pseudo_thread_id=8/*!*/;
    SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
    SET @@session.sql_mode=1436549152/*!80005 &~0x1003ff00*//*!*/;
    SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
    /*!\C latin1 *//*!*/;
    SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
    SET @@session.lc_time_names=0/*!*/;
    SET @@session.collation_database=DEFAULT/*!*/;
    DROP TABLE `cats` /* generated by server */
    /*!*/;
    # at 1985
    #200527 13:05:06 server id 2  end_log_pos 2050 CRC32 0x2f8d0249 	Anonymous_GTID	last_committed=6	sequence_number=7	rbr_only=yes	original_committed_timestamp=0	immediate_commit_timestamp=0	transaction_length=0
    /*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
    # original_commit_timestamp=0 (1969-12-31 19:00:00.000000 EST)
    # immediate_commit_timestamp=0 (1969-12-31 19:00:00.000000 EST)
    /*!80001 SET @@session.original_commit_timestamp=0*//*!*/;
    /*!80014 SET @@session.original_server_version=0*//*!*/;
    /*!80014 SET @@session.immediate_server_version=0*//*!*/;
    SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
    # at 2050
    #200527 13:05:06 server id 2  end_log_pos 2122 CRC32 0x56280bb1 	Query	thread_id=8	exec_time=0	error_code=0

    mysqlbinlog的输出中,可以在二进制日志的 和 之间的段中找到该 语句DROP TABLE `pets`.`cats`, 这意味着该语句发生 日志位置 1868 之后,而日志位于该语句之后的位置 1985 。 # at 1868# at 1985DROP TABLE

    笔记

    Only use the --start-datetime and --stop-datetime options to help you find the actual event positions of interest. Using the two options to specify the range of binary log segment to apply is not recommended: there is a higher risk of missing binary log events when using the options. Use --start-position and --stop-position instead.

  3. Apply the events in binary log file to the server, starting with the log position your found in step 1 (assume it is 1006) and ending at the position you have found in step 2 that is before your point-in-time of interest (which is 1868):

    $> mysqlbinlog --start-position=1006 --stop-position=1868 /var/lib/mysql/bin.123456 \
             | mysql -u root -p

    The command recovers all the transactions from the starting position until just before the stop position. Because the output of mysqlbinlog includes SET TIMESTAMP statements before each SQL statement recorded, the recovered data and related MySQL logs reflect the original times at which the transactions were executed.

    Your database has now been restored to the point-in-time of interest, tp, right before the table pets.cats was dropped.

  4. 除了已经完成的时间点恢复之外,如果您还想重新执行 您感兴趣的时间点之后的所有语句,请再次使用mysqlbinlog将之后的所有事件应用到服务器。我们在第 2 步中注意到,在我们要跳过的语句之后,日志位于 1985 位置;我们可以将它用于 选项,以便包含位置之后的任何语句: tp--start-position

    $> mysqlbinlog --start-position=1985 /var/lib/mysql/bin.123456 \
             | mysql -u root -p

    您的数据库已恢复二进制日志文件中记录的最新语句,但已跳过所选事件。