凌云的博客

行胜于言

MySQL 日志备份恢复

分类:MySQL| 发布时间:2019-11-15 00:16:00


MySQL 日志备份恢复,简单来说就是备份的时候将 MySQL 的 binlog 文件备份起来, 在恢复的时候重放备份的 binlog。

结合 MySQL 物理备份和日志备份可以做到将 MySQL 还原到从物理备份以来到最新的日志备份之间的任意时间点。

日志备份

在进行日志备份之前需要先确认日志文件的连续性。 也就是说,需要保证至上一次进行物理备份以来的所有日志都还在当前系统,或者在备份系统中。

如果发现日志文件不连续,则需要先进行一次物理备份。

在确保日志文件是连续的情况,就可以进行日志备份了:

首先要做的就是使用 flush logs 命令,flush logs 可以 MySQL rotate 到下一个 binlog 进行写入。 这样,我们就可以达到将 flush logs 之前的 binlog 都备份起来的目的。

例如:

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000015 |       241 |
| mysql-bin.000016 |       241 |
| mysql-bin.000017 |       217 |
| mysql-bin.000018 |       824 |
| mysql-bin.000019 |      1081 |
| mysql-bin.000020 |       241 |
| mysql-bin.000021 |       217 |
| mysql-bin.000022 |       241 |
| mysql-bin.000023 |       194 |
+------------------+-----------+
9 rows in set (0.00 sec)

mysql> flush logs;
Query OK, 0 rows affected (0.01 sec)

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000015 |       241 |
| mysql-bin.000016 |       241 |
| mysql-bin.000017 |       217 |
| mysql-bin.000018 |       824 |
| mysql-bin.000019 |      1081 |
| mysql-bin.000020 |       241 |
| mysql-bin.000021 |       217 |
| mysql-bin.000022 |       241 |
| mysql-bin.000023 |       241 |
| mysql-bin.000024 |      1104 |
+------------------+-----------+

原本 MySQL 正在将 binlog 写入 mysql-bin.000023,flush logs 会让 MySQL 关闭 mysql-bin.000023,然后打开 mysql-bin.000024 作为当前二进制日志写入。 这样我们就可以安全的备份 mysql-bin.000015 到 mysql-bin.000023 这几个日志文件了。

日志备份阶段,可以使用 rsync、scp 等工具将其备份,当然也可以先使用 tar 将其打包后再备走。

备份完成后,在确认备份集有效的情况下,可以将日志清掉

mysql> purge master logs to 'mysql-bin.000024';

恢复

进行日志恢复前,需要先进行物理恢复。进行物理恢复后,再使用 mysqlbinlog 重放物理备份之后的日志。 如下:

mysqlbinlog --start-position=# log-files | mysql -uroot -p12345

这里有个问题需要解决,就是 我们应该从哪个日志的哪个位置开始重放?

其实在进行物理备份的时候,xtrabackup 生成了一个 xtrabackup_binlog_info 文件,里面包含了我们需要的信息。

cat base/xtrabackup_binlog_info
mysql-bin.000023	194

因此,在这里我们的应该从 mysql-bin.000023 的偏移 194 开始进行恢复。

mysqlbinlog --start-position=194 mysql-bin.000023 | mysql -uroot -p12345
mysqlbinlog --start-position=194 mysql-bin.000024 | mysql -uroot -p12345

如果我们需要恢复到特定时间点,可以加上 --stop-datetime 或者 --stop-position 参数,比如:

mysqlbinlog --start-position=194 mysql-bin.000023 --stop-datetime="2019-11-14 12:19:57" | mysql -uroot -p12345
mysqlbinlog --start-position=194 mysql-bin.000024 --stop-datetime="2019-11-14 12:19:57" | mysql -uroot -p12345

在这里,有个可以优化的地方,如果 mysql-bin.000024 是我们要恢复的时间点之后生成的 binlog 。 那么,第二条命令就没有必要执行了。 那么,如何知道这个日志的生成时间呢?

实际上,MySQL binlog 是由一个一个 event 构成的,每个 event 都有一个 header,header 上有一个 Timestamp 字段记录了 event 的时间戳。 因此,我们只需要查看 binlog 第一个 event 的 Timestamp 就可以知道这个 binlog 记录的是哪个时间点开始的日志。

为了达到这个目的,可以使用我写的一个 binlog 的解析工具 达到:

$ ./binlogparser -p log/mysql-bin.000024 -c 1
----------------------EVENT-------------------
HEADER
	timestamp: 1573737597 (2019-11-14 13:19:57 +0000 UTC)
	event_type: FORMAT_DESCRIPTION_EVENT
	server_id: 1
	event_size: 119
	log_pos: 123
	flags: 0
PAYLOAD
	binlog_version: 0
	mysql_server_version: 5.7.25-0ubuntu0.16.04.2-log
	create_timestamp: 0
	event_header_length: 0
	event_type_header_length: [56 13 0 8 0 18 0 4 4 4 4 18 0 0 95 0 4 26 8 0 0 0 8 8 8 2 0 0 0 10 10 10 42 42 0 18 52 0]

可以看到 mysql-bin.000024 是 2019-11-14 13:19:57 生成的,在我们指定时间点 2019-11-14 12:19:57 之后,因此第二条命令是没必要执行的。

参考