Linux,  MySQL

MySQL如何利用逻辑备份+binlog恢复数据?

零背景说明

本文档记录在CentOS 7上运行的MySQL 8.0.29版本的数据库,利用逻辑备份+binary log来恢复数据的操作步骤和流程。

一 准备环境

0 OS和数据库信息

#OS
[root@node-2 ~]# uname -rm
3.10.0-862.el7.x86_64 x86_64
[root@node-2 ~]# cat /etc/redhat-release 
CentOS Linux release 7.5.1804 (Core) 
[root@node-2 ~]# 

数据库:

[root@node-2 ~]# mysql -V
mysql  Ver 8.0.29 for Linux on x86_64 (MySQL Community Server - GPL)
[root@node-2 ~]# 

1 数据库开启binary log

如果没有开启,则需要手工通过修改配置文件/etc/my.cnf来开启MySQL的binary log。

我这里,通过rpm的方式来安装的MySQL 8.0.29版本的MySQL数据库,默认开启了binary log。

mysql> select @@version;
+-----------+
| @@version |
+-----------+
| 8.0.29    |
+-----------+
1 row in set (0.00 sec)
​
mysql> show variables like 'log_bin%';
+---------------------------------+-----------------------------+
| Variable_name                   | Value                       |
+---------------------------------+-----------------------------+
| log_bin                         | ON                          |
| log_bin_basename                | /var/lib/mysql/binlog       |
| log_bin_index                   | /var/lib/mysql/binlog.index |
| log_bin_trust_function_creators | OFF                         |
| log_bin_use_v1_row_events       | OFF                         |
+---------------------------------+-----------------------------+
5 rows in set (0.00 sec)
​
mysql> 

操作系统上,确认binary log 信息:

[root@node-2 ~]# ll /var/lib/mysql/binlog.*
-rw-r----- 1 mysql mysql 1218575 10月 17 16:01 /var/lib/mysql/binlog.000001
-rw-r----- 1 mysql mysql      16 10月 17 15:14 /var/lib/mysql/binlog.index
[root@node-2 ~]# 

2 创建测试表和数据

mysql> create database testdb;
Query OK, 1 row affected (0.04 sec)
​
mysql> use testdb;
Database changed
mysql> create table t1(id int);
Query OK, 0 rows affected (0.78 sec)
​
mysql> insert into t1 values(1);
Query OK, 1 row affected (0.08 sec)
​
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
​
mysql> select * from t1;
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
​
mysql> 

3 逻辑备份数据库

[root@node-2 ~]# mysqldump -uroot -pOnlyou_168 --all-databases --flush-logs --source-data >/data/backup/`date +%F`_mysql.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
[root@node-2 ~]# 

其中:

–all-databases,表示备份所有的数据库;

–flush-logs, 表示在逻辑备份前,对服务器执行一次切换binary log的操作。这有啥用呢?意味着将来恢复的时候,直接拿我这个逻辑备份的dump文件,就可以恢复到日志切换前的那个状态。

–source-date,表示在逻辑备份的dump文件中,会记录binary log的详细切换信息。配合上面的参数–flush-logs使用。旧版本的MySQL对应的该命令行选项是:–master-data “This option is deprecated and will be removed in a future version. Use source-data instead.”

查看逻辑备份dump文件内容:

-- MySQL dump 10.13  Distrib 8.0.29, for Linux (x86_64)
--
-- Host: localhost    Database:
-- ------------------------------------------------------
-- Server version       8.0.29
​
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!50606 SET @OLD_INNODB_STATS_AUTO_RECALC=@@INNODB_STATS_AUTO_RECALC */;
/*!50606 SET GLOBAL INNODB_STATS_AUTO_RECALC=OFF */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
​
--
-- Position to start replication or point-in-time recovery from
--
​
CHANGE MASTER TO MASTER_LOG_FILE='binlog.000002', MASTER_LOG_POS=157;
​
--
-- Current Database: `mysql`

注意,上面的一行,CHANGE MASTER TO MASTER_LOG_FILE=’binlog.000002′, MASTER_LOG_POS=157;

意味着,将来,我这个dump文件可以把数据库恢复到截止binary log为binlog.000002的position=157的位置处。即:至少可以恢复出testdb库里的表t1中的记录id=1的数据。如果,还需要继续恢复数据的话,就需要从binlog.000002的position=157的位置处,继续向后应用binary log的内容来恢复数据。

4 创建新的测试数据

mysql> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
​
Database changed
mysql> select * from t1;
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.01 sec)
​
mysql> insert into t1 values(200);
Query OK, 1 row affected (0.07 sec)
​
mysql> select * from t1;
+------+
| id   |
+------+
|    1 |
|  200 |
+------+
2 rows in set (0.00 sec)
​
mysql> 

5 备份binary log

[root@node-2 ~]# ll /var/lib/mysql/binlog.*
-rw-r----- 1 mysql mysql 1219279 10月 17 16:08 /var/lib/mysql/binlog.000001
-rw-r----- 1 mysql mysql     434 10月 17 16:30 /var/lib/mysql/binlog.000002
-rw-r----- 1 mysql mysql      32 10月 17 16:08 /var/lib/mysql/binlog.index
[root@node-2 ~]# mkdir -p /data/backup/binlog
[root@node-2 ~]# cp /var/lib/mysql/binlog.* /data/backup/binlog/

6 模拟故障

删除MySQL的所有数据文件和日志文件

[root@node-2 ~]# systemctl stop mysqld
[root@node-2 ~]# rm -rf /var/lib/mysql/*
[root@node-2 ~]# 

7 执行恢复

首先,重新启动初始化MySQL数据库:

[root@node-2 ~]# systemctl start mysqld
[root@node-2 ~]# grep "temporary" /var/log/mysqld.log 
2022-10-17T08:33:21.380612Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: k4/Y!8G)JuTd
[root@node-2 ~]# 

修改MySQL root口令:

[root@node-2 ~]# mysql -uroot -p'k4/Y!8G)JuTd'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.29
​
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
​
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
​
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
​
mysql> alter user root@'localhost' identified by 'Onlyou_168';
Query OK, 0 rows affected (0.08 sec)
​
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)
​
mysql>

重新初始化的MySQL数据库实例,压根儿不存在testdb数据库。

读取逻辑备份文件来恢复数据:

mysql> source /data/backup/2022-10-17_mysql.sql
...
Query OK, 0 rows affected (0.00 sec)
​
Query OK, 0 rows affected (0.00 sec)
​
mysql> 

验证恢复结果:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| testdb             |
+--------------------+
5 rows in set (0.00 sec)
​
mysql> select * from testdb.t1;
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
​
mysql> 

发现只有1条记录,这是符合预期的。我们当时执行逻辑备份时,testdb库中的t1表,有且仅有1条记录,id=1。

id=200是我们在备份之后,数据库的binary log为binlog.000002时,从position=157的位置处,开始记日志时,才写入数据库里的数据。

那么,我们想要恢复该条记录时,就的通过binary log为binlog.000002时,从position=157的位置处,向后继续恢复。

通过mysqlbinlog命令来读取binary log的内容,并且通过管道传递给mysql命令去执行。

[root@node-2 binlog]# pwd
/data/backup/binlog
[root@node-2 binlog]# ll
总用量 1200
-rw-r----- 1 root root 1219279 10月 17 16:31 binlog.000001
-rw-r----- 1 root root     434 10月 17 16:31 binlog.000002
-rw-r----- 1 root root      32 10月 17 16:31 binlog.index
[root@node-2 binlog]# mysqlbinlog binlog.000002 --start-position=158|mysql -uroot -p'Onlyou_168'
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@node-2 binlog]# mysql -uroot -p'Onlyou_168'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.0.29 MySQL Community Server - GPL
​
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
​
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
​
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
​
mysql> select * from testdb.t1;
+------+
| id   |
+------+
|    1 |
|  200 |
+------+
2 rows in set (0.00 sec)
​
mysql> 

最后,确定数据,恢复成功。

二 binary log和redo log的区别

MySQL里的binary log用于记录数据库里的DDL、DML操作,主要用于replication和point in time recovery。默认路径在$DATADIR路径下,名为binlog.xxxxxx;

MySQL里和Oracle对应的redo log是transaction log,默认路径是$DATADIR下,名为ib_logfile0和ib_logfile1。主要用于innodb引擎。所以,命名类似于ib_xxx。

三 小结

通过逻辑备份+binary log来恢复数据的一个快速上手,了解MySQL和其它关系型数据库的不同之处:MySQL既有binary log,也有单独的类似于Oracle的redo log;

了解通过mysqldump备份数据库的选项:–databases –flush-logs –source-data

四 参考链接

Difference between transaction log and redo log in MySQL