MySql增量恢复

一、 使用二进制日志的时间点恢复

注意

本节和下一节中的许多示例都使用mysql客户端来处理mysqlbinlog生成的二进制日志输出。如果您的二进制日志包含\0(null)字符,那么mysql将无法解析该输出,除非您使用--binary模式选项调用它。

时间点恢复的信息源是在完全备份操作之后生成的一组二进制日志文件。因此,为了允许服务器恢复到某个时间点,必须在其上启用二进制日志记录,这是MySQL 8.0的默认设置

要从二进制日志中恢复数据,您必须知道当前二进制日志文件的名称和位置。默认情况下,服务器在数据目录中创建二进制日志文件,但可以使用--log-bin选项指定路径名,以将文件放置在不同的位置。要查看所有二进制日志文件的列表,请使用以下语句:

复制代码
mysql> SHOW BINARY LOGS;

要确定当前二进制日志文件的名称,请发出 以下声明:

复制代码
mysql> SHOW MASTER STATUS;

mysqlbinlog实用程序将二进制日志文件中的事件从二进制格式转换为文本,以便可以查看或应用它们。mysqlbinlog具有根据事件时间或事件在日志中的位置选择二进制日志部分的选项。

应用二进制日志中的事件会导致重新执行它们所表示的数据修改。这样可以在给定的时间段内恢复数据更改。要应用二进制日志中的事件,请使用mysql客户端处理mysqlbinlog输出:

复制代码
$> mysqlbinlog binlog_files | mysql -u root -p

如果二进制日志文件已经加密(可以从MySQL 8.0.14开始),则mysqlbinlog不能像上面的示例那样直接读取它们,而是可以使用--read from remote server(-R)选项从服务器读取它们。例如:

复制代码
$> mysqlbinlog --read-from-remote-server --host=host_name --port=3306  --user=root --password --ssl-mode=required  binlog_files | mysql -u root -p

这里,选项--ssl mode=required用于确保二进制日志文件中的数据在传输过程中受到保护,因为它是以未加密的格式发送到mysqlbinlog的。

重要

对于SSL模式,VERIFY_CA和VERIFY_IDENTITY是比REQUIRED更好的选择,因为它们有助于防止中间人攻击。若要实现其中一个设置,必须首先确保服务器的CA证书对环境中使用它的所有客户端都可靠可用,否则将导致可用性问题。

当您需要确定事件时间或位置以在执行事件之前选择部分日志内容时,查看日志内容非常有用。要查看日志中的事件,请将mysqlbinlog输出发送到一个分页程序中:

复制代码
$> mysqlbinlog binlog_files | more

或者,将输出保存在文件中,然后在 文本编辑器:

复制代码
$> mysqlbinlog binlog_files > tmpfile
$> ... edit tmpfile ...

编辑文件后,按如下方式应用内容:

复制代码
$> mysql -u root -p < tmpfile

如果在MySQL服务器上有多个二进制日志要应用,请使用单个连接来应用要处理的所有二进制日志文件的内容。以下是一种方法:

复制代码
$> mysqlbinlog binlog.000001 binlog.000002 | mysql -u root -p

另一种方法是将整个日志写入单个文件,然后处理该文件:

复制代码
$> mysqlbinlog binlog.000001 >  /tmp/statements.sql
$> mysqlbinlog binlog.000002 >> /tmp/statements.sql
$> mysql -u root -p -e "source /tmp/statements.sql"

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

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

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

注意

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

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

    $> 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语句可以在二进制日志的232行#和355行#之间的段中找到,这意味着该语句发生在日志位置232之后,并且该日志位于DROP TABLE语句之后的位置355。

注意

仅使用 --开始日期时间和 --停止日期时间选项来帮助您找到 利息。使用这两个选项指定 不建议应用二进制日志段:有一个 使用 选项。改用 --start-position 和 --stop-position。

  1. 将二进制日志文件中的事件应用于服务器,从您在步骤1中找到的日志位置开始(假设为155),到您在步骤2中找到的位于感兴趣时间点之前的位置结束(即232):

    $> mysqlbinlog --start-position=155 --stop-position=232 /var/lib/mysql/bin.123456
    | mysql -u root -p

该命令将所有事务从起始位置恢复到停止位置之前。由于mysqlbinlog的输出在记录每条SQL语句之前都包含SET TIMESTAMP语句,因此恢复的数据和相关的MySQL日志反映了事务执行的原始时间。

您的数据库现在已经恢复到感兴趣的时间点tp,就在表pets.cats被删除之前。

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

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

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

相关推荐
走在路上的菜鸟1 小时前
Android学Dart学习笔记第四节 基本类型
android·笔记·学习
百锦再1 小时前
第21章 构建命令行工具
android·java·图像处理·python·计算机视觉·rust·django
就是ping不通的蛋黄派1 小时前
MySQL数据库 管理与维护
数据库·mysql
skyhh3 小时前
Android Studio 最新版汉化
android·ide·android studio
路人甲ing..3 小时前
Android Studio 快速的制作一个可以在 手机上跑的app
android·java·linux·智能手机·android studio
携欢6 小时前
PortSwigger靶场之Web shell upload via path traversal靶场通关秘籍
android
找不到、了11 小时前
MySQL 索引下推(ICP)的实战,彻底提升查询性能
数据库·mysql
kitty_hi11 小时前
mysql主从配置升级,从mysql5.7升级到mysql8.4
linux·数据库·mysql·adb
q***133413 小时前
Linux系统离线部署MySQL详细教程(带每步骤图文教程)
linux·mysql·adb
消失的旧时光-194314 小时前
Android ADB指令大全详解
android·adb