MySQL备份与恢复+策略方案选择

MySQL备份与恢复

数据库备份的分类

从物理与逻辑的角度

(1)物理备份:指对数据库操作系统的物理文件(如数据文件、日志文件等)的备份。物理备份又可以分为脱机备份(冷备份)和联机各份(热备份)。

  • 冷备份:在关闭数据库时进行的备份操作,能够较好地保证数据库的完整性。
  • 热备份:在数据库运行状态中进行操作,这种备份方法依赖于数据库的日志文件。

(2)逻辑备份:指对数据库逻辑组件(如表等数据库对象)的备份。

从数据库的备份策略角度,备份可分为完全备份、差异备份和增量备份。

(1)完全备份:每次对数据进行完整的备份。可以备份整个数据库,包含用户表、系统表、索引、视图和存储过程等所有数据库对象。但它需要花费更多的时间和空间,所以,做一次完全备份的周期要长些。

(2)差异备份:备份那些自从上次完全备份之后被修改过的文件,只备份数据库部分的内容。它比最初的完全备份小,因为只包含自上次完全备份以来所改变的数据库。它的优点是存储和恢复速度快。

(3)增量备份:只有那些在上次完全备份或者增量备份后被修改的文件才会被备份。

逻辑备份的特点是:直接生成SQL语句,在恢复的时候执行备份的SQL语句实现数据库数据的重现。

物理备份的特点是:拷贝相关数据文件。

这二种备份差异:逻辑备份备份、还原慢,但备份文件占用的空间小;物理备份备份还原快,备份文件占用空间大。

逻辑备份的主要工具:mysqldump,MySQL自带的备份命令,不需要额外安装。

物理备份工具主要有:xtrabackup,第三方工具,需要额外安装。

MySQL备份工具介绍

mysqldump

命令格式

MySQL自带的一个很好使用的数据库备份命令,语法如下:

mysqldump -u 用户名 -p 数据库名 > 备份文件名

**注意:**mysqldump全量备份不会备份系统库,即不会备份:information_schema、performance_schema、sys

实例说明

准备数据:

-- 查看备份前数据
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. -e "use crm_db;show tables;select *from userinfo;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------------+
| Tables_in_crm_db |
+------------------+
| userinfo         |
+------------------+
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
+----+----------+------+

-- 执行备份命令
[root@izbp1aosct92mcgcq5dhqpz home]# mysqldump -uroot -pWo123456. crm_db > /home/crm_db_bak.sql

-- 查看备份结果
[root@izbp1aosct92mcgcq5dhqpz home]# egrep -v "#|\*|--|^$" /home/crm_db_bak.sql
DROP TABLE IF EXISTS `userinfo`;
CREATE TABLE `userinfo` (
  `id` int(10) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `age` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
LOCK TABLES `userinfo` WRITE;
INSERT INTO `userinfo` VALUES (1,'zhangsan',18);
UNLOCK TABLES;

参数说明

上面使用mysqldump简单的方式进行备份,mysqldump还有很多参数。

1、–default-character-set

该参数指定了备份的字符集,可解决备份乱码的问题。

[root@hadoop-slave1 temp]# mysqldump -uroot -pWo123456. --default-character-set=utf8 crm_db > /home/crm_db_bak.sql

2、-A, --all-databases

作用是备份所有的库,例如:

[root@hadoop-slave1 /]# mysqldump -uroot -pWo123456 -A > /home/all.sql

注意:不会备份系统库,即不会备份:information_schema、performance_schema、sys

3、–databases, -B

参数后面所有名字参量都被看作数据库名。

-B参数的作用是在备份中增加了:

  • 创建数据库
  • 连接数据库(use database)
[root@izbp1aosct92mcgcq5dhqpz home]# mysqldump -uroot -pWo123456. -B crm_db > /home/crm_db_bak.sql

-- 查看内容
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `crm_db` /*!40100 DEFAULT CHARACTER SET latin1 */;
USE `crm_db`;

DROP TABLE IF EXISTS `userinfo`;

CREATE TABLE `userinfo` (
  `id` int(10) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `age` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

LOCK TABLES `userinfo` WRITE;

INSERT INTO `userinfo` VALUES (1,'zhangsan',18);

UNLOCK TABLES;

可以看到这与之前的不同在于多了以下两条语句:

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `crm_db`;      -- 创建数据库
USE `crm_db`;                                           -- 链接数据库

4、–compact

该参数可以优化备份文件大小,导出更少的输出信息。去掉注释和头尾等结构。

该参数适合测试时使用。

[root@hadoop-slave1 temp]# mysqldump -uroot -p123456 --compact crm_db > /temp/crm_db_compat_bak_.sql

--查看完整的备份内容
[root@izbp1aosct92mcgcq5dhqpz home]# cat crm_db_compat_bak_.sql 
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `userinfo` (
  `id` int(10) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `age` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO `userinfo` VALUES (1,'zhangsan',18);

5、gzip

gzip可以对MySQL备份文件的内容进行压缩

[root@izbp1aosct92mcgcq5dhqpz home]# mysqldump -uroot -pWo123456. -B crm_db|gzip > /home/crm_db_bak_gzip.sql.gz

-- 可以查看普通备份和压缩后的文件大小比较:
[root@izbp1aosct92mcgcq5dhqpz home]# ll
-rw-r--r-- 1 root  root   766 5月  22 10:38 crm_db_bak_gzip.sql.gz
-rw-r--r-- 1 root  root  2056 5月  22 10:29 crm_db_bak.sql

6、-F, --flush-logs

用于刷新 binlog参数,在/etc/my.cnf配置文件中如果启用了log-bin就会在安装的数据目录中生成binlog日志信息。

在没有进行备份时,和binlog相关的文件有:

-rw-r----- 1 mysql mysql      154 5月  22 10:58 mysqlbin.000001
-rw-r----- 1 mysql mysql       18 5月  22 10:58 mysqlbin.index

使用-F参数进行备份:

[root@izbp1aosct92mcgcq5dhqpz mysql]# mysqldump -uroot -pWo123456. -A -B -F > /home/all.sql

-- 查看binlog相关文件
-rw-r----- 1 mysql mysql      200 5月  22 11:04 mysqlbin.000001
-rw-r----- 1 mysql mysql      200 5月  22 11:04 mysqlbin.000002
-rw-r----- 1 mysql mysql      154 5月  22 11:04 mysqlbin.000003
-rw-r----- 1 mysql mysql       54 5月  22 11:04 mysqlbin.index

binlog文件被刷新了,也就意味着如果进行数据恢复,只需要从mysql-bin.000003之后进行增量恢复,这个文件之前的已经进行了全量备份了(在all.sql文件中)。

这个参数主要就是切割binlog日志,记录备份的位置,防止恢复数据进行全量恢复而出错。

7、–master-data

这个参数也是记录binlog的位置,找到恢复的点,例如:

[root@izbp1aosct92mcgcq5dhqpz mysql]# mysqldump -uroot -pWo123456. --compact --master-data -B crm_db  > /home/crm_db.sql

-- 查看备份的文件内容
[root@izbp1aosct92mcgcq5dhqpz home]# cat crm_db.sql 
CHANGE MASTER TO MASTER_LOG_FILE='mysqlbin.000003', MASTER_LOG_POS=154;

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `crm_db` /*!40100 DEFAULT CHARACTER SET latin1 */;

USE `crm_db`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `userinfo` (
  `id` int(10) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `age` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO `userinfo` VALUES (1,'zhangsan',18);

可以看到备份的文件内容中,多了一行:

CHANGE MASTER TO MASTER_LOG_FILE='mysqlbin.000003', MASTER_LOG_POS=154;

这是记录了binlog日志的信息,也就是说在这个位置之前的已经全部备份了,只需要通过binlog恢复这个点之后的内容即可。

对于查看mysqlbin.000003文件的内容,通过mysqlbinlog命令:

[root@izbp1aosct92mcgcq5dhqpz mysql]# mysqlbinlog mysqlbin.000003

增量备份

上面例子中,使用使用-F参数进行了全量备份;

[root@izbp1aosct92mcgcq5dhqpz mysql]# mysqldump -uroot -pWo123456. -A -B -F > /home/all.sql

可以查看到binlog相关文件:

-rw-r----- 1 mysql mysql      200 522 11:04 mysqlbin.000001
-rw-r----- 1 mysql mysql      200 522 11:04 mysqlbin.000002
-rw-r----- 1 mysql mysql      154 522 11:04 mysqlbin.000003
-rw-r----- 1 mysql mysql       54 522 11:04 mysqlbin.index

从原来的000001增加到了000003.

时间来到了第二天下班时间,需要进行增量备份。而这一天所有的操作都保存在003文件中。

mysqladmin -u root -pWo123456. flush-logs
# 执行该语句代表刷新日志,此时会发现多出一个004文件

-rw-r----- 1 mysql mysql      200 522 11:04 mysqlbin.000001
-rw-r----- 1 mysql mysql      200 522 11:04 mysqlbin.000002
-rw-r----- 1 mysql mysql      154 522 11:04 mysqlbin.000003
-rw-r----- 1 mysql mysql      154 522 11:26 mysqlbin.000004
-rw-r----- 1 mysql mysql       54 522 11:04 mysqlbin.index

# 增量备份
cp mysqlbin.000003 /backcup/

恢复:

# 恢复mysqlbin.000003中的数据
mysqlbinlog -d crm_db mysqlbin.000003 > bin3.sql
mysql -uroot -pWo123456. crm_db < bin3.sql

备份库、表练习

1、多库备份

假设现在数据库中有多个库,上述使用的一直是一个库crm_db为例:现在新建一个库crm_db_1,然后同时进行备份。

# 同时备份crm_db、crm_db_1库
[root@izbp1aosct92mcgcq5dhqpz home]# mysqldump -uroot -pWo123456. -B crm_db crm_db_1|gzip > /home/crm_db_all_bak.sql.gz

上面的-B参数在生产环境常用,并且有以下的功能:

  • 后面可以接多个库进行备份
  • 备份文件中会增加创建数据库的信息(create database dbname…)
  • 备份文件中会增加连接数据库的信息(use dbname)

2、分库备份

上面是对多个库进行备份,并且备份到了一个备份文件中了,那么如何将每一个库都备份一个自己独有的备份文件呢?

分库备份就是一个备份语句备份一个库,如果有多个库就执行多条相同的备份单个库的备份语句。

注意的是每一个库的备份文件名可以用其库名代替,后面.sql即可。

[root@izbp1aosct92mcgcq5dhqpz home]# mysqldump -uroot -pWo123456. -B crm_db|gzip > /home/crm_db_bak_gzip.sql.gz
crm_db_bak_gzip.sql.gz

[root@izbp1aosct92mcgcq5dhqpz home]# mysqldump -uroot -pWo123456. -B crm_db_1|gzip > /home/crm_db_1_bak_gzip.sql.gz
crm_db_1_bak_gzip.sql.gz

就是一条一条的写。

假如有1000个库怎么办,下面有两种方式可以进行分库备份:

1、

mysql -uroot -pWo123456. -e "show databases;"|grep -Evi "database|infor|perfor"|sed -r 's#^([a-z].*$)#mysqldump -uroot -pWo123456. -B \1|gzip>/temp/\1.sql.gz#g'|bash

2、

首先创建一个脚本:

for dbname in `mysql -uroot -pWo123456. -e "show databases;"|grep -Evi "database|infor|perfor"`
do
  mysqldump -uroot -pWo123456. -B $dbname|gzip>/temp/${dbname}_bak.sql.gz
done

然后执行。

分库备份的意义就是,如果某一个库出现问题时只需要备份这一个库就可以了,而将所有的库备份在一个备份文件中,这样恢复起来比较麻烦。

3、单表备份

语法:

mysqldump -uroot 用户名 -p 数据库名 表名 > 备份文件名

例如:

[root@izbp1aosct92mcgcq5dhqpz home]# mysqldump -uroot -pWo123456. crm_db userinfo > /home/t1.sql
t1.sql

注意:不要加-B参数,因为库名后面就是表名。

4、多表备份

语法:

mysqldump -uroot 用户名 -p 数据库名 表名1 表名2 > 备份文件名

如果库名后紧跟多个表的时候会将多个表写入同一个备份文件,这样的话如果向恢复某一个表时很难将备份文件拆开,那么这也就意味着我们需要像分库一样进行分表备份。

只需要每条语句备份一个表即可:

mysqldump -uroot -pWo123456. crm_db userinfo > /home/t1.sql
mysqldump -uroot -pWo123456. crm_db product> /home/t2.sql

也可以像分库备份一样写一个脚本文件来进行备份。

5、备份数据库表结构

有时候我们只需要备份数据表结构而不需要数据,这是需要使用到-d参数。

[root@izbp1aosct92mcgcq5dhqpz home]# mysqldump -uroot -pWo123456. -B -d crm_db > /home/crm_db__bak.sql
crm_db__bak.sql

# 查看备份
[root@izbp1aosct92mcgcq5dhqpz home]# egrep -v "#|\*|--|^$" /home/crm_db__bak.sql
USE `crm_db`;
DROP TABLE IF EXISTS `userinfo`;
CREATE TABLE `userinfo` (
  `id` int(10) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `age` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

6、备份数据表数据

上面是只备份数据表结构,那么如果只想备份数据表的数据,就使用-t参数。

[root@izbp1aosct92mcgcq5dhqpz home]# mysqldump -uroot -pWo123456. -t crm_db > /home/crm_db_bak.sql

# 查看内容
[root@izbp1aosct92mcgcq5dhqpz home]# egrep -v "#|\*|--|^$" /home/crm_db_bak.sql
LOCK TABLES `userinfo` WRITE;
INSERT INTO `userinfo` VALUES (1,'zhangsan',18);
UNLOCK TABLES;

mysqldump关键参数总结

# 参数查看通过
[root@hadoop-slave1 data]# mysqldump --help

# 以下关键参数说明
1、-A备份所有的库
2、-B指定多个库,增加建库和use语句
3、--compact 去掉注释,适合调试,不用于生产
4、-F刷新binlog日志
5、--master-data 增加binlog日志文件名和对应的位置点
6、-d只备份表结构
7、t 只备份表数据
8、--single-transaction 适合innodb事务数据库备份,保证数据在备份时的一致性,设定本次会话的隔离级别为REPEATABLE READ,确保本次会话dump时,不会看到其它会话已经提交的数据

# 推荐使用的innodb备份命令
mysqldump -uroot -pWo123456. -A -B -F --master-data=2 --events --single-transaction|gzip>/home/all.sql.gz
# myisam备份命令
mysqldump -uroot -pWo123456. -A -B -F --master-data=2 -x --events |gzip>/home/all.sql.gz

数据恢复

source命令恢复

先进行备份,然后通过source命令恢复:

# 备份crm_db数据库
[root@izbp1aosct92mcgcq5dhqpz ~]# mysqldump -uroot -pWo123456. -B crm_db > /home/crm_db_bak.sql
# 查看备份结果
[root@izbp1aosct92mcgcq5dhqpz home]# ls /home
crm_db_bak.sql

# 删除已经备份的数据库
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. -e 'drop database crm_db;show databases;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| crm_db_1           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

# 恢复备份
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. -e 'source /home/crm_db_bak.sql'

# 查看数据库
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. -e 'show databases;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| crm_db             |
| crm_db_1           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
# 查看数据库中表数据
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. -e 'show databases;use crm_db;select * from userinfo;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| crm_db             |
| crm_db_1           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
+----+----------+------+

mysql命令恢复(标准)

1、备份时带-B参数

-B参数在备份时有连接数据库和创建数据库的作用,所以如果在备份时指定了该参数,那么在恢复时就无需指定具体的恢复的数据库:

# 备份crm_db数据库
[root@izbp1aosct92mcgcq5dhqpz ~]# mysqldump -uroot -pWo123456. -B crm_db > /home/crm_db_bak.sql
# 查看备份结果
[root@izbp1aosct92mcgcq5dhqpz home]# ls /home
crm_db_bak.sql

# 删除已经备份的数据库
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. -e 'drop database crm_db;show databases;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| crm_db_1           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

# 恢复;无需指定数据库。
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. < /home/crm_db_bak.sql

# 查看数据库
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. -e 'show databases;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| crm_db             |
| crm_db_1           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
# 查看数据库中表数据
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. -e 'show databases;use crm_db;select * from userinfo;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| crm_db             |
| crm_db_1           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
+----+----------+------+

2、备份时未带-B参数

这也就意味着在恢复数据库数据时必须指定恢复到那个数据库,并且这个数据库已经是存在的。

# 备份crm_db_1数据库
[root@izbp1aosct92mcgcq5dhqpz ~]# mysqldump -uroot -pWo123456. crm_db_1 > /home/crm_db_1_bak.sql

# 删除已经备份的数据库
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. -e 'drop database crm_db_1;show databases;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| crm_db             |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

# 恢复;需指定数据库,且此数据库必须存在。
# 不指定数据库恢复:报错。
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456.  < /home/crm_db_1_bak.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1046 (3D000) at line 22: No database selected
# 指定不存在的同名数据库:报错。
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. crm_db_1  < /home/crm_db_1_bak.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1049 (42000): Unknown database 'crm_db_1'
# 创建数据库,并指定:成功!
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. crm_db_1  < /home/crm_db_1_bak.sql
mysql: [Warning] Using a password on the command line interface can be insecure.

# 查看数据库中表数据
[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. -e 'show databases;use crm_db_1;select * from userinfo1;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| crm_db             |
| crm_db_1           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  2 | lisi     |   19 |
+----+----------+------+

binlog日志恢复

MySQL的binlog日志用于记录MySQL中的增、删、该操作,当你没有备份时就只能依靠它来进行数据的恢复了。

1、恢复的种类

  • 全库
root@hadoop-slave1 data]# mysqlbinlog mysql-bin.000002 > all.sql
  • 分库

比如从binlog日志中抽离出crm_db的sql操作信息:

root@hadoop-slave1 data]# mysqlbinlog -d crm_db mysql-bin.000002 > crm_db.sql

2、增量恢复的方式

  • 基于位置点的增量恢复
 mysqlbinlog  mysql-bin.000002 --start-position=107 --stop-position=208 -r db.sql

注意:结尾的日志比较特殊,不会被包含,即输出208以前的日志。

如果开始位置到结束,则无需制定–stop-position参数:

 mysqlbinlog  mysql-bin.000002 --start-position=107 -r db.sql

如果没有指定–start-position参数,则是开始到指定的结束位置:

 mysqlbinlog  mysql-bin.000002 --stop-position=208 -r db.sql
  • 基于时间的增量恢复
 mysqlbinlog  mysql-bin.000002 --start-datetime='2020-8-30 11:10:20' --stop-datetime='2020-8-30 14:30:20' -r db.sql

实战

场景:

数据库crm_db中的数据在某个时间点操作失误,想恢复数据。

1、查看crm_db数据库相关信息

[root@izbp1aosct92mcgcq5dhqpz home]# mysql -uroot -pWo123456. -e 'use crm_db;show tables;select * from userinfo;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------------+
| Tables_in_crm_db |
+------------------+
| userinfo         |
+------------------+
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
|  2 | lisi     |   19 |
|  3 | wangwu   |   20 |
+----+----------+------+

2、对crm_db进行备份

[root@izbp1aosct92mcgcq5dhqpz home]# mysqldump -uroot -pWo123456. -B crm_db > /home/crm_db.sql
crm_db.sql

3、异常产生

在这一步由于更改数据导致数据异常

mysql> update userinfo set username='zhaoliu';
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3  Changed: 3  Warnings: 0

mysql> select * from userinfo;
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhaoliu  |   18 |
|  2 | zhaoliu  |   19 |
|  3 | zhaoliu  |   20 |
+----+----------+------+
3 rows in set (0.00 sec)

由于update使用不当,导致错误产生,此时需要进行恢复,但是在恢复的过程中仍旧会有新的数据不断插入,所以需要将binlog日志先进行分割

4、binlog日志分割

在数据库不停止服务时,进行日志分割;也可在 对crm_db进行备份 时带上参数直接进行日志分割。

# 分割前文件
-rw-r----- 1 mysql mysql      200 522 11:04 mysqlbin.000001
-rw-r----- 1 mysql mysql      200 522 11:04 mysqlbin.000002
-rw-r----- 1 mysql mysql     6517 522 14:13 mysqlbin.000003
-rw-r----- 1 mysql mysql       54 522 11:04 mysqlbin.index

# 分割
[root@hadoop-slave1 /]# mysqladmin -uroot -pWo123456. flush-log

-rw-r----- 1 mysql mysql      200 522 11:04 mysqlbin.000001
-rw-r----- 1 mysql mysql      200 522 11:04 mysqlbin.000002
-rw-r----- 1 mysql mysql     6563 522 14:16 mysqlbin.000003
-rw-r----- 1 mysql mysql      154 522 14:16 mysqlbin.000004

分割后多了一个mysqlbin.000004文件,也就是说后面写的内容都会写在这个文件中,现在需要处理的就是mysqlbin.000003文件

5、备份恢复

首先,我们将还未出错前的数据通过备份文件crm_db.sql进行恢复:

[root@izbp1aosct92mcgcq5dhqpz mysql]# mysql -uroot -pWo123456. < /home/crm_db.sql

# 查看数据,发现恢复到了出错之前。
[root@izbp1aosct92mcgcq5dhqpz mysql]#  mysql -uroot -pWo123456. -e 'use crm_db;select * from userinfo;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
|  2 | lisi     |   19 |
|  3 | wangwu   |   20 |
+----+----------+------+

现在恢复的是备份前的数据,缺少的是备份的时间点到出错这段时间的数据,那么这段时间只能通过binlog日志来获取了。

6、binlog恢复数据

# binlog日志生成sql
[root@izbp1aosct92mcgcq5dhqpz mysql]# mysqlbinlog -d crm_db mysqlbin.000003 > bin3.sql

# 删除bin.sql中update更新的语句,然后恢复
vim bin3.sql
	# at 6294
    #210522 14:13:03 server id 1  end_log_pos 6351 CRC32 0x113671be         Table_map: `crm_db`.`userinfo` mapped to number 127
    # at 6351
    #210522 14:13:03 server id 1  end_log_pos 6486 CRC32 0x1562c6a6         Update_rows: table id 127 flags: STMT_END_F

    BINLOG '
    76CoYBMBAAAAOQAAAM8YAAAAAH8AAAAAAAEABmNybV9kYgAIdXNlcmluZm8AAwMPAwL/AAa+cTYR
    76CoYB8BAAAAhwAAAFYZAAAAAH8AAAAAAAEAAgAD///4AQAAAAh6aGFuZ3NhbhIAAAD4AQAAAAd6
    aGFvbGl1EgAAAPgCAAAABGxpc2kTAAAA+AIAAAAHemhhb2xpdRMAAAD4AwAAAAZ3YW5nd3UUAAAA
    +AMAAAAHemhhb2xpdRQAAACmxmIV
    '/*!*/;
    # at 6486
    #210522 14:13:03 server id 1  end_log_pos 6517 CRC32 0x97e84440         Xid = 955
    COMMIT/*!*/;
    # at 6517
    #210522 14:16:12 server id 1  end_log_pos 6563 CRC32 0x7f066414         Rotate to mysqlbin.000004  pos: 4
    SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
    DELIMITER ;
    # End of log file
    /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
    /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
# 删除下面的BINLOG:
	BINLOG '
    76CoYBMBAAAAOQAAAM8YAAAAAH8AAAAAAAEABmNybV9kYgAIdXNlcmluZm8AAwMPAwL/AAa+cTYR
    76CoYB8BAAAAhwAAAFYZAAAAAH8AAAAAAAEAAgAD///4AQAAAAh6aGFuZ3NhbhIAAAD4AQAAAAd6
    aGFvbGl1EgAAAPgCAAAABGxpc2kTAAAA+AIAAAAHemhhb2xpdRMAAAD4AwAAAAZ3YW5nd3UUAAAA
    +AMAAAAHemhhb2xpdRQAAACmxmIV
    '/*!*/;

# 执行恢复
[root@izbp1aosct92mcgcq5dhqpz mysql]# mysql -uroot -pWo123456. crm_db < bin3.sql

# 查看数据
[root@izbp1aosct92mcgcq5dhqpz mysql]# mysql -uroot -pWo123456. -e 'use crm_db;select * from userinfo;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
|  2 | lisi     |   19 |
|  3 | wangwu   |   20 |
+----+----------+------+

上面恢复的数据时备份时间点到出错这段时间的数据,那么出错之后的数据因为进行了日志分割,所以它在mysqlbin.000004日志文件中,只需要再将其恢复即可:

# 恢复mysqlbin.000004中的数据
[root@izbp1aosct92mcgcq5dhqpz mysql]# mysqlbinlog -d crm_db mysqlbin.000004 > bin4.sql
[root@izbp1aosct92mcgcq5dhqpz mysql]# mysql -uroot -pWo123456. crm_db < bin4.sql

xtrabackup

xtrabackup是Percona公司CTO Vadim参与开发的一款基于InnoDB的在线热备工具,具有开源,免费,支持在线热备,备份恢复速度快,占用磁盘空间小等特点,并且支持不同情况下的多种备份形式。

在实际生产环境中增量备份是非常实用的,如果数据大于50G或100G,存储空间足够的情况下,可以每天进行完整备份,如果每天产生的数据量较大,需要定制数据备份策略。

例如每周实用完整备份,周一到周六增量备份。而Percona-Xtrabackup就是为了实现增量备份而出现的一款主流备份工具,xtrabakackup有2个工具,分别是xtrabakup、innobakupe。

Xtrabackup中主要包含两个工具:
xtrabackup:是用于热备innodb,xtradb表中数据的工具,不能备份其他类型的表,也不能备份数据表结构;
innobackupex:是将xtrabackup进行封装的perl脚本,提供了备份myisam表的能力。

优点:

(1)备份速度快,物理备份可靠

(2)备份过程不会打断正在执行的事务(无需锁表)

(3)能够基于压缩等功能节约磁盘空间和流量

(4)自动备份校验

(5)还原速度快

(6)可以流传将备份传输到另外一台机器上

(7)在不增加服务器负载的情况备份数据

安装

可以选择rpm包方式安装,也可以下载源码包编译安装,这里直接采用rpm包的方式进行安装

wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.9/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.9-1.el7.x86_64.rpm

yum install -y percona-xtrabackup-24-2.4.9-1.el7.x86_64.rpm

[root@izbp1aosct92mcgcq5dhqpz mysql]# rpm -qa |grep xtrabackup
percona-xtrabackup-24-2.4.9-1.el7.x86_64

使用innobackupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件,这些文件会被保存到一个以时间命名的目录当中。

在备份的同时,innobackupex还会在备份目录中创建如下文件:

(1)xtrabackup_checkpoints -- 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息:

每个InnoDB页(通常为16k大小)
都会包含一个日志序列号,即LSN,LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。

(2)xtrabackup_binlog_info  --  mysql服务器当前正在使用的二进制日志文件及备份这一刻位置二进制日志时间的位置。

(3)xtrabackup_binlog_pos_innodb  --  二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。

(4)xtrabackup_binary  --  备份中用到的xtrabackup的可执行文件;

(5)backup-my.cnf  --  备份命令用到的配置选项信息:

在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录:如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据。

注意:备份时需启动MySQL,恢复时需关闭MySQL,清空mysql数据目录且不能重新初始化,恢复数据后应该立即进行一次完全备份

innobackupex常用参数

--user=USER                     指定备份用户,不指定的话为当前系统用户
--password=PASSWD               指定备份用户密码
--port=PORT                     指定数据库端口
--defaults-group=GROUP-NAME     在多实例的时候使用
--host=HOST                     指定备份的主机,可以为远程数据库服务器
--apply-log                     应用 BACKUP-DIR 中的 xtrabackup_logfile 事务日志文件。
                                一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。
                                因此,此时数据文件仍处于不一致状态。
                                “准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件使得数据文件处于一致性状态。
--databases                     指定需要备份的数据库,多个数据库之间以空格分开。
                                格式为:--databases="db1[.tb1] db2[.tb2]" 多个库之间以空格隔开,如果此选项不被指定,将会备份所有的数据库。
--defaults-file                 指定mysql的配置文件,只能从给定的文件中读取默认选项。
                                且必须作为命令行上的第一个选项;必须是一个真实的文件,它不能是一个符号链接。
--copy-back                     将备份数据复制回原始位置
--incremental                   增量备份,后面跟要增量备份的路径
--incremental-basedir=DIRECTORY 增量备份时使用指向上一次的增量备份所在的目录
--incremental-dir=DIRECTORY     增量备份还原的时候用来合并增量备份到全量,用来指定全备路径
--rsync                         加快本地文件传输,适用于non-InnoDB数据库引擎。不与--stream共用
--no-timestamp                  生成的备份文件不以时间戳为目录.
--tables-file=FILE              此选项的参数需要是一个文件名,此文件中每行包含一个要备份的表的完整名称,格式为databasename.tablename。
                                该选项传递给 xtrabackup --tables-file,与--tables选项不同,只有要备份的表的库才会被创建。
                                注意:部分备份(--include、--tables-file、--database)需要开启 innodb_file_per_table 。
--redo-only                     在“准备基本完整备份” 和 “合并所有的增量备份(除了最后一个增备)”时使用此选项。
                                它直接传递给xtrabackup的 xtrabackup --apply-log-only 选项,使xtrabackup跳过"undo"阶段,只做"redo"操作。
                                如果后面还有增量备份应用到这个全备,这是必要的

全量备份

innobackupex --defaults-file=/etc/my.cnf --user=root --password=Wo123456. --socket=/var/lib/mysql/mysql.sock  /backups/

备份文件说明

[root@izbp1aosct92mcgcq5dhqpz 2021-05-22_17-17-07]# ll
总用量 77872
-rw-r----- 1 root root      424 522 17:17 backup-my.cnf      #备份命令用到的配置选项信息
drwxr-x--- 2 root root     4096 522 17:17 crm_db
-rw-r----- 1 root root      454 522 17:17 ib_buffer_pool     #buffer pool 中的热数据,当设置innodb_buffer_pool_dump_at_shutdown=1 ,在关闭 MySQL 时,会把内存中的热数据保存在磁盘里 ib_buffer_pool 文件中,位于数据目录下。
-rw-r----- 1 root root 79691776 522 17:17 ibdata1            #备份的共享表空间文件
drwxr-x--- 2 root root     4096 522 17:17 mysql
drwxr-x--- 2 root root     4096 522 17:17 performance_schema
drwxr-x--- 2 root root    12288 522 17:17 sys
-rw-r----- 1 root root       22 522 17:17 xtrabackup_binlog_info  #mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置;
-rw-r----- 1 root root      113 522 17:17 xtrabackup_checkpoints  #备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;
-rw-r----- 1 root root      529 522 17:17 xtrabackup_info         #记录备份的基本信息,uuid、备份命令、备份时间、binlog、LSN、以及其他加密压缩等信息。 
-rw-r----- 1 root root     2560 522 17:17 xtrabackup_logfile      #备份的重做日志文件。

全备恢复

# 准备一个完全备份
[root@izbp1aosct92mcgcq5dhqpz 2021-05-22_17-17-07]# innobackupex --apply-log /backups/2021-05-22_17-17-07

# 关闭数据库
systemctl stop mysqld

# 删除原有数据文件
mkdir /home/bak
mv /var/lib/mysql/* /home/bak

# 执行恢复
innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /backups/2021-05-22_17-17-07

# 查看mysql数据文件
[root@izbp1aosct92mcgcq5dhqpz ~]# cd /var/lib/mysql
[root@izbp1aosct92mcgcq5dhqpz mysql]# ls
crm_db  ib_buffer_pool  ibdata1  ib_logfile0  ib_logfile1  ibtmp1  mysql  performance_schema  sys  xtrabackup_binlog_pos_innodb  xtrabackup_info

# 更改权限
chown -R mysql.mysql /var/lib/mysql

#启动数据库
systemctl start mysqld
systemctl status mysqld

# 登录数据库
[root@izbp1aosct92mcgcq5dhqpz bak]# mysql -uroot -pWo123456.
# 查看表数据
mysql> use crm_db;
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 userinfo;
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
|  2 | lisi     |   19 |
|  3 | wangwu   |   20 |
+----+----------+------+
3 rows in set (0.00 sec)

增量备份

- 直接以之前的全备为基准,在其基础上做增量备份

增量备份:

# 1.插入测试数据
insert into userinfo values (4, "zengliang1",1);

# 2.做增量备份1,以之前的全量备份``/backups/2021-05-22_17-17-07``为基准
innobackupex --defaults-file=/etc/my.cnf --user=root --password=Wo123456. --socket=/var/lib/mysql/mysql.sock --incremental /backups/inc --incremental-basedir=/backups/2021-05-22_17-17-07/ --parallel=2

# 3.再插入测试数据
insert into userinfo values (5, "zengliang2",2);

# 4.做增量备份2:(以增量1为基准 /backups/inc/2021-05-22_17-38-45)
innobackupex --defaults-file=/etc/my.cnf --user=root --password=Wo123456. --socket=/var/lib/mysql/mysql.sock --incremental /backups/inc --incremental-basedir=/backups/inc/2021-05-22_17-38-45/ --parallel=2

增量备份恢复:

增量备份的恢复需要有3个步骤

  1. 恢复完全备份
  2. 恢复增量备份到完全备份(开始恢复的增量备份要添加–redo-only参数,到最后一次增量备份要去掉–redo-only)
  3. 对整体的完全备份进行恢复,回滚未提交的数据

先恢复到增量备份1

# 先恢复到增量备份1
## 1.准备一个全备
[root@izbp1aosct92mcgcq5dhqpz inc]# innobackupex --apply-log --redo-only /backups/2021-05-22_17-17-07

## 2.将增量1应用到完全备份
innobackupex --apply-log --redo-only /backups/2021-05-22_17-17-07/ --incremental-dir=/backups/inc/2021-05-22_17-38-45

## 4.把所有合在一起的完全备份整体进行一次apply操作,回滚未提交的数据
[root@izbp1aosct92mcgcq5dhqpz 2021-05-22_17-38-45]# innobackupex --apply-log /backups/2021-05-22_17-17-07

# 关闭数据库
systemctl stop mysqld

# 删除原有数据文件
mkdir /home/bak
mv /var/lib/mysql/* /home/bak

# 执行恢复
innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /backups/2021-05-22_17-17-07

# 查看mysql数据文件
[root@izbp1aosct92mcgcq5dhqpz ~]# cd /var/lib/mysql
[root@izbp1aosct92mcgcq5dhqpz mysql]# ls
crm_db  ib_buffer_pool  ibdata1  ib_logfile0  ib_logfile1  ibtmp1  mysql  performance_schema  sys  xtrabackup_binlog_pos_innodb  xtrabackup_info

# 更改权限
chown -R mysql.mysql /var/lib/mysql

#启动数据库
systemctl start mysqld
systemctl status mysqld

# 登录数据库
[root@izbp1aosct92mcgcq5dhqpz bak]# mysql -uroot -pWo123456.
# 查看表数据
mysql> use crm_db;
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 userinfo;
+----+------------+------+
| id | username   | age  |
+----+------------+------+
|  1 | zhangsan   |   18 |
|  2 | lisi       |   19 |
|  3 | wangwu     |   20 |
|  4 | zengliang1 |    1 |
+----+------------+------+
4 rows in set (0.00 sec)
### 增量1已经恢复成功!

恢复到增量备份2

## 1.准备一个全备
[root@izbp1aosct92mcgcq5dhqpz inc]# innobackupex --apply-log --redo-only /backups/2021-05-22_17-17-07

## 2.将增量2应用到完全备份
innobackupex --apply-log --redo-only /backups/2021-05-22_17-17-07/ --incremental-dir=/backups/inc/2021-05-22_17-41-30

## 4.把所有合在一起的完全备份整体进行一次apply操作,回滚未提交的数据
[root@izbp1aosct92mcgcq5dhqpz 2021-05-22_17-38-45]# innobackupex --apply-log /backups/2021-05-22_17-17-07

# 关闭数据库
systemctl stop mysqld

# 删除原有数据文件
mkdir /home/bak
mv /var/lib/mysql/* /home/bak

# 执行恢复
innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /backups/2021-05-22_17-17-07

# 查看mysql数据文件
[root@izbp1aosct92mcgcq5dhqpz ~]# cd /var/lib/mysql
[root@izbp1aosct92mcgcq5dhqpz mysql]# ls
crm_db  ib_buffer_pool  ibdata1  ib_logfile0  ib_logfile1  ibtmp1  mysql  performance_schema  sys  xtrabackup_binlog_pos_innodb  xtrabackup_info

# 更改权限
chown -R mysql.mysql /var/lib/mysql

#启动数据库
systemctl start mysqld
systemctl status mysqld

# 登录数据库
[root@izbp1aosct92mcgcq5dhqpz bak]# mysql -uroot -pWo123456.
# 查看表数据
mysql> use crm_db;
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 userinfo;
+----+------------+------+
| id | username   | age  |
+----+------------+------+
|  1 | zhangsan   |   18 |
|  2 | lisi       |   19 |
|  3 | wangwu     |   20 |
|  4 | zengliang1 |    1 |
|  5 | zengliang2 |    2 |
+----+------------+------+
5 rows in set (0.00 sec)
### 增量2已经恢复成功!

而此时所有的增量备份也都已经同步到全备份中了。

备份单库或单表

innobackupex --defaults-file=/etc/my.cnf --user=root --password=Wo123456. --databases="crm_db_1" --socket=/var/lib/mysql/mysql.sock  /backups/

–databases:指定需要备份的数据库,多个数据库之间以空格分开。

格式为:–databases=“db1[.tb1] db2[.tb2]” 多个库之间以空格隔开,如果此选项不被指定,将会备份所有的数据库。

注意:

备份单库实际上是一种特殊的增量备份,如果需要恢复该单库备份,仍然需要一个全量备份作为基准,将该单库备份合并到全备中,再恢复全备。

具体操作和增量备份中操作一致。

比较

mysqldump

  • 适用于数据量不大的数据库备份。
  • 备份与恢复时速度慢。
  • 只能进行全量备份,增量备份不支持。
  • 增量备份需要结合binlog日志

xtrabackup

  • 备份速度快,恢复速度快,备份文件占用空间大
  • 可以全量备份也可以增量备份

需要灵活备份单个库或者单个表,并且随时能够不停止数据库服务恢复时,使用mysqldump。

xtrabackup适用于数据量大的备份,适用于每天一次增量备份,每周一次全量备份的模式。恢复时,data目录需要是空的。

MySQL备份策略

1、主从复制+mysqldump恢复(优选)

MySQL的主从复制主要是为了减轻主库的压力而产生的一种读写分离式优化方案。

主从复制原理:从库配置读取主库的binlog日志,当主库发生改变后,从库根据binlog日志完成修改,以保证和主库数据一致。

由于主从复制是实时同步数据的,所以主从复制用来做备份也是一个很好的方案。

(1)配置主从复制

已有MySQL服务

  1. 在主服务器配置文件:
[mysqld]
#开启日志
log‐bin = mysql‐bin
#设置服务id,主从不能一致
server‐id = 1
#设置需要同步的数据库
binlog‐do‐db=user_db
#屏蔽系统库同步
binlog‐ignore‐db=mysql
binlog‐ignore‐db=information_schema
binlog‐ignore‐db=performance_schema
  1. 在从服务器配置文件:
[mysqld]
#开启日志
log‐bin = mysql‐bin
#设置服务id,主从不能一致
server‐id = 2
#设置需要同步的数据库
replicate_wild_do_table=user_db.%
#屏蔽系统库同步
replicate_wild_ignore_table=mysql.%
replicate_wild_ignore_table=information_schema.%
replicate_wild_ignore_table=performance_schema.%
  1. 主、从服务器重启

  2. 为了方便,创建用于主从复制的账号

    也可以不创建,直接使用root用户。

在主服务器:

--授权主从复制专用账号
GRANT REPLICATION SLAVE ON *.* TO 'db_sync'@'%' IDENTIFIED BY 'db_sync';
--刷新权限
FLUSH PRIVILEGES;

--确认位点 记录下文件名以及位点
show master status;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w3Cq5VjN-1622015825796)(MySQL备份与恢复.assets/image-20210520093822672.png)]

  1. 主从数据同步设置:

从数据库中:

--先停止同步
STOP SLAVE;

--修改从库指向到主库,使用上一步记录的文件名以及位点
CHANGE MASTER TO
master_host = 'localhost',
master_user = 'db_sync',
master_password = 'db_sync',
master_log_file = 'mysql-bin.000002',
master_log_pos = 154;

--启动同步
START SLAVE;

--查看Slave_IO_Runing和Slave_SQL_Runing字段值都为Yes,表示同步配置成功。如果不为Yes,请排查相关异常。
show slave status;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qp4dseKx-1622015825797)(MySQL备份与恢复.assets/image-20210520094008852.png)]

踩坑

mysql主从同步解决Slave_IO_Running:No问题

停止从数据库服务,删除data目录下auto.conf文件后,重新启动服务即可。

测试时搭建环境:

docker-compose 启动两个 mysql 服务:

文件结构:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a0XC75t3-1622015825801)(MySQL备份与恢复.assets/image-20210520094510881.png)]

文件结构解释:

  • config.mysql-master.master.cnf : 主mysql的配置

  • config.mysql-slave.slave.cnf : 从mysql的配置

  • data.mysql-master : 主mysql的数据存储文件;里面不能有文件

  • data.mysql-slave : 从mysql的数据存储文件;里面不能有文件

  • docker-compose.yml : docker-compose配置文件

  • mysql_connector.sh : 配置mysql的主从配置

主 mysql 的配置:master.cnf

[mysqld]
## 设置server_id,一般设置为IP,注意要唯一
server_id=100
## 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql
## 开启二进制日志功能,可以随便取,最好有含义(关键就是这里了)
log-bin=replicas-mysql-bin
## 为每个session分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
## 主从复制的格式(mixed,statement,row,默认格式是statement)
binlog_format=mixed
## 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062

从 mysql 的配置:slave.cnf

[mysqld]
## 设置server_id,一般设置为IP,注意要唯一
server_id=101
## 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=replicas-mysql-slave1-bin
## 为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
## 主从复制的格式(mixed,statement,row,默认格式是statement)
binlog_format=mixed
## 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=replicas-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## 防止改变数据(除了特殊的线程)
read_only=1

配置mysql主从的脚本:mysql_connector.sh

#!/bin/bash
BASE_PATH=$(dirname $0)

echo "Waiting for mysql to get up"
# Give 60 seconds for master and slave to come up
sleep 60

echo "Create MySQL Servers (master / slave repl)"
echo "-----------------"


echo "* Create replication user"

mysql --host mysqlslave -uroot -p$MYSQL_SLAVE_PASSWORD -AN -e 'STOP SLAVE;';
mysql --host mysqlmaster -uroot -p$MYSQL_MASTER_PASSWORD -AN -e 'RESET SLAVE ALL;';

mysql --host mysqlmaster -uroot -p$MYSQL_MASTER_PASSWORD -AN -e "CREATE USER '$MYSQL_REPLICATION_USER'@'%';"
mysql --host mysqlmaster -uroot -p$MYSQL_MASTER_PASSWORD -AN -e "GRANT REPLICATION SLAVE ON *.* TO '$MYSQL_REPLICATION_USER'@'%' IDENTIFIED BY '$MYSQL_REPLICATION_PASSWORD';"
mysql --host mysqlmaster -uroot -p$MYSQL_MASTER_PASSWORD -AN -e 'flush privileges;'


echo "* Set MySQL01 as master on MySQL02"

MYSQL01_Position=$(eval "mysql --host mysqlmaster -uroot -p$MYSQL_MASTER_PASSWORD -e 'show master status \G' | grep Position | sed -n -e 's/^.*: //p'")
MYSQL01_File=$(eval "mysql --host mysqlmaster -uroot -p$MYSQL_MASTER_PASSWORD -e 'show master status \G'     | grep File     | sed -n -e 's/^.*: //p'")
MASTER_IP=$(eval "getent hosts mysqlmaster|awk '{print \$1}'")
echo $MASTER_IP
mysql --host mysqlslave -uroot -p$MYSQL_SLAVE_PASSWORD -AN -e "CHANGE MASTER TO master_host='mysqlmaster', master_port=3306,
        master_user='$MYSQL_REPLICATION_USER', master_password='$MYSQL_REPLICATION_PASSWORD', master_log_file='$MYSQL01_File',
        master_log_pos=$MYSQL01_Position;"

echo "* Set MySQL02 as master on MySQL01"

MYSQL02_Position=$(eval "mysql --host mysqlslave -uroot -p$MYSQL_SLAVE_PASSWORD -e 'show master status \G' | grep Position | sed -n -e 's/^.*: //p'")
MYSQL02_File=$(eval "mysql --host mysqlslave -uroot -p$MYSQL_SLAVE_PASSWORD -e 'show master status \G'     | grep File     | sed -n -e 's/^.*: //p'")

SLAVE_IP=$(eval "getent hosts mysqlslave|awk '{print \$1}'")
echo $SLAVE_IP
mysql --host mysqlmaster -uroot -p$MYSQL_MASTER_PASSWORD -AN -e "CHANGE MASTER TO master_host='mysqlslave', master_port=3306,
        master_user='$MYSQL_REPLICATION_USER', master_password='$MYSQL_REPLICATION_PASSWORD', master_log_file='$MYSQL02_File',
        master_log_pos=$MYSQL02_Position;"

echo "* Start Slave on both Servers"
mysql --host mysqlslave -uroot -p$MYSQL_SLAVE_PASSWORD -AN -e "start slave;"

echo "Increase the max_connections to 2000"
mysql --host mysqlmaster -uroot -p$MYSQL_MASTER_PASSWORD -AN -e 'set GLOBAL max_connections=2000';
mysql --host mysqlslave -uroot -p$MYSQL_SLAVE_PASSWORD -AN -e 'set GLOBAL max_connections=2000';

mysql --host mysqlslave -uroot -p$MYSQL_SLAVE_PASSWORD -e "show slave status \G"

echo "MySQL servers created!"
echo "--------------------"
echo
echo Variables available fo you :-
echo
echo MYSQL01_IP       : mysqlmaster
echo MYSQL02_IP       : mysqlslave

docker-compose 配置文件

version: '2'
services:
  mysqlmaster:
    image: mysql:5.7.15
    container_name: "mysql_master1"
    environment:
      - "MYSQL_ROOT_PASSWORD=root"
    volumes:
      - "./data/mysql-master:/var/lib/mysql/"
      - "./config/mysql-master:/etc/mysql/conf.d/"
    ports:
      - "3306:3306"
  mysqlslave:
    image: mysql:5.7.15
    container_name: "mysql_slave1"
    environment:
      - "MYSQL_ROOT_PASSWORD=root"
    volumes:
      - "./data/mysql-slave:/var/lib/mysql/"
      - "./config/mysql-slave:/etc/mysql/conf.d/"
    ports:
      - "3307:3306"
  mysqlconfigure:
    image: mysql:5.7.15
    container_name: "mysql_configure"
    environment:
      - "MYSQL_SLAVE_PASSWORD=root"
      - "MYSQL_MASTER_PASSWORD=root"
      - "MYSQL_ROOT_PASSWORD=root"
      - "MYSQL_REPLICATION_USER=repl"
      - "MYSQL_REPLICATION_PASSWORD=repl"
    volumes:
      - "./mysql_connector.sh:/tmp/mysql_connector.sh"
    command: /bin/bash -x /tmp/mysql_connector.sh

查看是否启动成功:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XM3Tcg3n-1622015825803)(MySQL备份与恢复.assets/image-20210520095309024.png)]

踩坑

启动成功后发现未实现主从复制。

解决办法:

按照 已有MySQL服务 中的配置重新走一遍,再次测试,成功!

(2)从库备份恢复

使用mysqldump备份:

mysqldump -uroot -pWo123456. -A -B > /home/all.sql

恢复:

将all.sql文件复制到主库所在服务器,执行如下命令:

mysql -uroot -pWo123456. < /home/all.sql

2、xtrabackup定时备份

xtrabackup做一个全备份,后面定时做增量备份。

做一次全量备份,生成文件夹,第一次做增量备份时使用全量备份文件做基准,后面每次都是用上一次增量文件做基准。

恢复时,将所有增量备份合并到全量备份中,恢复全量。

增量备份脚本:

#!/bin/bash
# backup增量备份脚本,使用之前先做一次全量备份。
# 全量备份放在/backups下,增量备份放在/backups/inc下。

  DIR="/backups"
  INCDIR="/backups/inc"

  if [ "$(ls -A $INCDIR)" ];
    then
      echo "$INCDIR is not Empty"
      incsondir="$(ls /backups/inc -ltr |tail -1|awk '{print $NF}')"
      incdir="$INCDIR/$incsondir"
      incnum="$(ls -l $INCDIR |grep "^d" |wc -l)"
      echo "第$(($incnum+1))次增量备份开始:"
    else
      echo "$INCDIR is Empty"
      incsondir="$(ls /backups/ -lt |tail -1|awk '{print $NF}')"
      incdir="$DIR/$incsondir"
      echo "第1次增量备份开始:"
  fi

  echo "===> $incdir"

  innobackupex --defaults-file=/etc/my.cnf --user=root --password=Wo123456. --socket=/var/lib/mysql/mysql.sock --incremental $INCDIR --incremental-basedir=$incdir --parallel=2

  exit 0

创建定时任务:

[root@izbp1aosct92mcgcq5dhqpz testShell]# crontab -e
	* * * * * /home/testShell/test.sh
# 保存之后定时任务就创建好了,上面命令表示一分钟一次。
# 查看增量备份文件夹:
[root@izbp1aosct92mcgcq5dhqpz inc]# ls
2021-05-25_09-48-01  2021-05-25_09-49-01  2021-05-25_09-50-01  2021-05-25_09-51-01
# 可以看出,一分钟备份了一次。

# 删除定时任务:
[root@izbp1aosct92mcgcq5dhqpz testShell]# crontab -r

你可能感兴趣的:(MySQL,笔记,mysql优化)