分类: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 之后,因此第二条命令是没必要执行的。