MySQL线上数据备份及恢复策略

1 备份模式

  • 全量备份

    对应时间的数据是全量的一个备份

  • 差异备份

    自上一次完整备份后产生的数据,即每次都会备份一次自上次完整备份以后产生的所有数据,因此备份的数据包大小会随着日期越来越大,直到进行一次完整备份,但是差异备份结合完全备份恢复数据最为方便快捷。
    MySQL线上数据备份及恢复策略_第1张图片

  • 增量备份

    需要使用专业备份工具,涉及到完整备份后的数据时间识别,每次备份只会备份自上次备份之后到备份时间之内产生的数据,因此每次备份相对差异备份的数据较小,但是恢复数据不是很方便且恢复较慢,但是备份较快。
    MySQL线上数据备份及恢复策略_第2张图片

  • 时间点恢复

    上面三个备份节点都是一个定时的数据补偿,在定时备份完成后至任意时间节点前,这段时间出现问题就是Binlog能做的事情了

2 备份类型

  • 热备

    即在线对服务器做备份,数据库的读写操作均可正常进行,是要通过备份工具,myisam引擎不支持热备,inn oDB支持热备。

  • 温备

    服务在线,数据库只能进行读操作,不能进行写操作

  • 冷备

    即服务器不在线,离线备份。

  • 物理备份

    直接copy数据文件

    优点: 能够跨mysql的版本,恢复速度快,属于文件系统级别的

    缺点: 如果备份的数据源就是损坏的,则备份出的数据也是无法恢复的

  • 逻辑备份

    将数据库里的数据导出进行备份的方式就是逻辑备份

    优点: 恢复简单、备份的结果为ASCII文件,可以编辑,与存储引擎无关,可以通过网 络备份和恢复。

    缺点: 备份空间大,恢复慢,无法保证浮点数的精度,而且要重建索引,占CPU资源

3 MySQL常用的备份工具

  • mysqldump
    • mysql自带备份工具,是逻辑备份
    • innodb可以使用mysqldump进行热备
    • myisam可以使用mysqldump进行热备
    • 如果数据量较小可以使用
  • xtrabackup
    • Percona提供
    • 是一种物理备份工具
    • 支持完全备份,差异备份,增量备份
  • select语句直接备份
    • select*from a into outfile ‘/usr/local/a.bak’
  • cp命令
    • 只能进行冷备

4 数据一致性的理解

  • 数据一致性

    热备:数据库还依旧可以读写

    4:00进行定时备份,假设你的数据非常多,需要备份10-20分钟。小刘账户余额在4点还有200元,4点10分的时候,他转出了50元。假如在4点10分前还没有备份到余额表,4点11分开始备份余额表

  • 在备份场景下如何保持数据一致性

    • 第一种方式,在备份的时候给所有表加锁,只能读不能写
      • 如果锁表的时候可以把写入的数据先放入MQ或缓存,待备份完成补偿进数据库,还有就是考虑及时读的问题
    • 第二种方式:在备份开始的时候就对数据库的所有数据进行一个“快照”,快照记录了开始备份的那一刻的数据状态。

5 线上数据备份恢复策略实施

5.1 备份流程设计

  • 备份工具
  • 备份方式

1、考虑数据量:做备份工具的选型

  • 数量流量较小的情况下:mysqldump逻辑备份,导出的是sql
  • 如果我们的数据量非常大:xtrabackup

2、考虑我们的时间点补偿

  • 从上一个全量备份时间点到现在这个阶段的数据
  • Binlog:statement,row,mixed

3、备份方案

  • 全量备份 crontab -e (cron语法),定时执行备份脚本,时间选择在业务量小的时间点(记录我们的备份position)
  • 增量:binlog(statement和mixed模式,我们的SQL都是线性且可执行的)
  • statement和mixed的增量适用于正常情况下数据库无法打开使用或数据文件损坏
  • row特别适合单表数据异常恢复
  • 一定要确保线上不会出现直接执行的SQL

5.2 数据恢复流程

案例1:statement,mixed

student(id,score):4点100行数据,第二天8点的时候更新一条score,忘记加where条件,所有人score全部变为90了。

  • mysqldump:可以去到文件里找到student表把insert全部拿出来
  • xtrabackup:先要恢复到一个新数据库
  • 把4-8点间所有涉及到这个student表的DML除select外,以及我们出错的sql外,所有sql全部拿出来。
  • 按照这个顺序:4点student所有数据执行->执行Binlog的SQL

案例2:row

  • 找到position,通过mysqlbinlog导出变更的数据,只能用代码去调整他的记录变更为恢复的SQL

5.3使用mysqldump备份

mysqldump -uroot -p123456 --databases mydb > mydb.sql #导出带数据库的备份脚本
mysqldump -uroot -p123456 --databases mydb ad_user > mydb.sql #导出数据库指定表
mysqldump -uroot -p123456 --all-databases > mydb.sql #导出所有数据库
mysqldump -uroot -p123456 -d mydb > mydb.sql #导出数据库的所有表结构
mysqldump -uroot -p123456 -d mydb ad_user > mydb.sql #导出数据库的某个表结构

mysqldump常用来做温备,所以我们首先需要对想备份的数据施加读锁

施加读锁的方式:

  1. 直接再备份的时候添加选项

    –lock-all-tables 是哟啊对备份的数据库的所有表施加读锁

    –lock-table仅对单张表施加读锁,即使是备份整个数据库,它也是在我们备份某张表的时候才对该表施加读锁,因此适用于备份单张表。

mysql> flush tables with read lock;施加锁,表示把位于内存上的表统统都同步到磁盘上去,然后施加读锁
mysql> flush tables with read lock;释放锁

对于InnoDB存储引擎来讲,虽然你也能够请求到读锁,但是不代表它的所有数据都已经同步到磁盘上,因此当面对InnoDB的时候,我们要使用
mysql>show engine innodb status;
看看InnoDB所有的数据已经同步到磁盘上去了,才进行备份操作

备份策略:

完全备份+增量备份+二进制日志

先改数据库做完全备份:

[root@ecs-x-medium-2-linux-20200305093825 ~]#  mysqldump -uroot -p123456 --single-transaction --master-data=2 --databases ec_admin > /backup/ec_admin_`date +%F`.sql

--single-transaction: 基于此选项能实现热备InnoDB表;因此不需要同时使用--lock-all-tables;
--master-data=2 记录备份那一时刻的二进制日志的位置,并且注释掉,1是不注释的
--databases ec_admin 指定备份的数据库

回到mysql服务器端更新数据

mysql> create table tb1(id int);创建表
mysql> insert into tb1 value(1),(2),(3);

先查看完全备份文件里边记录的位置:

[root@ecs-x-medium-2-linux-20200305093825 backup]# cat ec_admin_2020-06-28.sql|less
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=120;

再回到服务器端:

mysql>show master status;
# 显示此时二进制日志的位置,从备份文件里边记录的位置到我们此时的位置,即为增量的部分
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      459 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

做增量备份

[root@ecs-x-medium-2-linux-20200305093825 bin]# mysqlbinlog --start-position=120 --stop-position=459 /usr/local/binlog/mysql-bin.000001 > /backup/ec_admin_`date +$F_%H`.sql

再回到服务器

mysql> insert into tb1 values (4),(5); 在插入一些数值
mysql> drop database ec_admin;   删除ec_admin库 

导出这次的二进制日志:

# 查看删除操作时二进制日志的位置
[root@ecs-x-medium-2-linux-20200305093825 bin]# mysqlbinlog --start-position=459 /usr/local/binlog/mysql-bin.000001
#导出二进制日志 
mysqlbinlog --start-position=15982 --stop-position=16176 /mydata/data/mysql-bin.000013 > /tmp/hellodb.sql  

先让mysql离线

mysql> set sql_log_bin=0;  关闭二进制日志
mysql> flush logs; 滚动下日志 

开始恢复数据:

//导入完全备份文件
[root@ecs-x-medium-2-linux-20200305093825 backup]# mysql -uroot -p123456 < /backup/ec_admin_11.sql

// 导入增量备份文件
[root@ecs-x-medium-2-linux-20200305093825 backup]# mysql -uroot -p123456 < /backup/ec_admimn_2020-06-28.sql

参考: https://www.cnblogs.com/fengzhongzhuzu/p/9101782.html

你可能感兴趣的:(MySQL)