zoukankan      html  css  js  c++  java
  • MySQL备份与恢复

    MySQL备份与恢复

    欢迎来到 来到大浪涛天的博客

    一、MySQL备份恢复

    1. 备份策略的设计与规划

    1-1. 在备份恢复中的职责

    1-1-1. 备份策略的设计

    1. 备份类型:
    • 热备 : 对于业务影响最小 InnoDB
    • 温备 : 长时间锁表备份 MyISAM
    • 冷备 : 业务关闭情况下备份
    1. 备份周期:
    • 根据数据量.
    1. 备份工具:
      mysqldump (MDP) , XBK (PBK) percona Xtrabackup , MEB(MySQL Enterprise BACKUP MEB) ,mysqlbinlog
    2. 备份方式:
    • 逻辑,文本方式备份,压缩比很大,比较省空间:
      全备 mysqldump
      增量 binlog (flush logs ,cp)
    • 物理备份:
      全备 : XBK
      增量 : XBK

    1-1-2. 检查备份可用性

    每天上班检查前一天晚上备份的文件是否正常,这个至关重要,防止某天备份出错,备份不成功,运维人员却对此完全不知情。

    crontab -l ----->
    备份脚本   ----->
    备份路径  ----->
    看备份日志,检查备份文件(大小,内容)

    1-1-3. 定期的恢复演练

    1. 定期恢复演练可以确认备份的可用性
    2. 可以增加运维人员对故障恢复的成熟程度,因为一般情况下都不用进行数据恢复,但是特殊情况下如设备硬盘损坏,又需要快速恢复数据
    3. 进行多种故障场景进去模拟,尽可能的形成一个体系

    1-1-4. 数据恢复

    需要确认好mysqldump定期备份的完整日志,然后确认好当天的二进制日志的结束点的位置,利用完整备份日志及二进制日志迅速恢复到故障之前的时间点。

    1-1-5. 数据迁移

    操作系统不同的迁移
    mysql   ->  mysql 
    其他    ->  mysql 
    mysql   ->   其他

    2. mysqldump 工具的使用

    2-1. mysql连接数据库的参数

    -u 用户名
    -p 密码
    -S 套接字
    -h 主机名
    -P 端口号
    
    基础备份参数
    -A 全备份
    [root@db01 backup]# mysqldump -uroot -p123 -A  >/backup/full.sql
    
    -B 针对某个或者某些库备份
    [root@db01 backup]# mysqldump -uroot -p123 -B world oldguo wordpress >/backup/db.sql
    
    库  表  前面接一个库名,后面都是接的是该库的表名,代表备份该库的表
    [root@db01 backup]# mysqldump -uroot -p123 world city country > /backup/tab.sql

    2-2. MySQL的特殊备份参数

    如果加上如下参数,备份的时候自动会把存储过程和函数,及事件和触发器都一起备份,因此一定要加
    -R 存储过程和函数
    -E 事件
    --triggers 触发器
    
    --master-data=2     
    (1) 记录备份时刻的binlog信息
    (2) 自动锁表
    	不加--single-transaction ,温备份
    	加了--single-transaction,对于InnoDB表不锁表备份(快照备份)
    
    --single-transaction 
    对于InnoDB的表,进行一致性快照备份,不锁表.
    
    因此完整的备份命令如下
    mysqldump -uroot -p123 -A -R -E --triggers --master-data=2 --single-transaction  >/backup/full.sql

    2-3. MySQL扩展参数

    在构建主从时,使用AUTO/ON
    --set-gtid-purged=AUTO/ON
    
    仅是做普通的本机备份恢复时,可以添加
    --set-gtid-purged=OFF  
    
    SET @@GLOBAL.GTID_PURGED='aa648280-a6a6-11e9-949f-000c294a1b3b:1-11';
    
    --max_allowed_packet=128M  控制的是备份时传输数据包的大小.
    
    mysqldump -uroot -p123 -A  -R  --max_allowed_packet=128M --triggers --set-gtid-purged=OFF --master-data=2  --single-transaction|gzip > /backup/full_$(date +%F).sql.gz

    2-4. MySQL恢复案例

    2-4-1. 网站系统故障演练删除数据库,利用binlog恢复数据库

    背景环境:

    1. 正在运行的网站系统,mysql-5.7.20 数据库,数据量50G,日业务增量1-5M。
    2. 备份策略:
      每天23:00点,计划任务调用mysqldump执行全备脚本
    3. 故障时间点:
      年底故障演练:模拟周三上午10点误删除数据库.

    处理思路:

    1. 停业务,挂维护页,避免数据的二次伤害
    2. 找一个临时库,恢复周二23:00全备
    3. 截取周二23:00 --- 周三10点误删除之间的binlog,恢复到临时库
    4. 测试可用性和完整性
    5. 处理方法
    • 方法一:直接使用临时库顶替原生产库,前端应用割接到新库
    • 方法二:将误删除的表用mysqldump导出,再source到原生产库
    1. 开启业务
    • 处理结果:经过20分钟的处理,最终业务恢复正常

    故障模拟演练

    1. 准备数据
    create database backup;
    use backup
    create table t1 (id int);
    insert into t1 values(1),(2),(3);
    commit;
    rm -rf /backup/*
    1. 周二 23:00全备
    
    mysqldump -uroot -padmin123 -A  -R  --triggers --set-gtid-purged=OFF --master-data=2  --single-transaction|gzip > /backup/full_$(date +%F).sql.gz

    注意:

    --master-data=2
    (1) 以注释的形式记录二进制日志信息
    (2) 自动开启锁表的功能
    
    --single-transaction 
    针对InnoDB进行快照备份
    -R 
    -E
    --triggers 
    
    --set-gtid-purged=AUTO/ON/OFF
    默认是auto 
    主从复制,忽略此参数 
    普通备份,可以OFF
    1. 模拟周二 23:00到周三 10点之间数据变化
    use backup
    insert into t1 values(11),(22),(33);
    commit;
    create table t2 (id int);
    insert into t2 values(11),(22),(33);
    commit;
    1. 模拟故障,删除表(只是模拟,不代表生产操作)
    drop database backup;
    1. 恢复过程
    • 准备临时数据库(多实例3308)
    systemctl start mysqld3307
    1. 准备备份
    • 准备全备:
    cd /backup
    gunzip full_2018-10-14.sql.gz 
    • 截取二进制日志
    -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=753;
    753
    1519 
    mysqlbinlog --skip-gtids   --start-position=753 --stop-position=1519  /data/binlog/mysql-bin.000002 >/backup/bin.sql
    1. 恢复备份到临时库
    mysql -S /data/3307/mysql.sock
    set sql_log_bin=0;
    source /backup/full_2019-07-15.sql
    source /backup/bin.sql
    1. 将故障表导出并恢复到生产
    mysqldump   -S /data/3307/mysql.sock -B  backup  >/backup/bak.sql
    mysql -uroot -p123 
    set sql_log_bin=0
    source /backup/bak.sql;

    2-5. 故障演练误删除表数据,利用gtids恢复故障表

    故障模拟如下:
    1、创建一个数据库 gtid
    2、在gtid下创建一张表t1
    3、插入5行任意数据
    4、全备
    5、插入两行数据,任意修改3行数据,删除1行数据
    6、删除所有数据
    7、再t1中又插入5行新数据,修改3行数据

    需求,跳过第六步恢复表数据

    1. 按要求模拟数据
     create database gtid charset utf8mb4;
     commit;
     use gtid;
     create table t1(id int);
     commit;
     insert into t1 values(1),(2),(3),(4),(5);
     commit;
     2. 全备数据库
      [root@test02 ~]# mysqldump -uroot -padmin123 -S /data/3307/mysql.sock -A --master-data=2 --single-transaction -R -E --triggers >/backup/1full.sql
      3. 继续模拟数据
      insert into t1 values(6),(7);
      update t1 set id=10 where id>4;
      delete from t1 where id=2;
      commit;
      delete from t1;
      commit;
      insert into t1 values(11),(12),(13),(14),(15);
      update t1 set id=30 where id >12;
      commit;
      4. 根据备份的结束点和events确定起点和终点,截取二进制日志
       SET @@GLOBAL.GTID_PURGED='9f5d3fcf-e215-11ea-9d2c-001c42063d8f:1-14';
       知道第6步的gtids号是17,而我们需要恢复的是15-19然后排除17
       [root@test02 ~]# mysqlbinlog --skip-gtids --include-gtids='9f5d3fcf-e215-11ea-9d2c-001c42063d8f:15-19' --exclude-gtids='9f5d3fcf-e215-11ea-9d2c-001c42063d8f:17' mysql-bin.000004 >/backup/1bin.sql;
       5. 打开测试库,并恢复全备库和截取的二进制日志
          set sql_log_bin=0;
          source /backup/1full.sql;
    	  source /backup/1bin.sql;
    	  set sql_log_bin=1;
        6. 将测试库的gtids库的t1表导出来
         mysqldump -uroot -padmin123 -S /data/3307/mysql.sock gtids t1 >/backup/gtid.sql
    	 7. 进入生产库,将数据导入到生产库中
    	   set sql_log_bin=0;
    	   use gtid;
    	   source /backup/gtid.sql
    	   set sql_log_bin=1;
         8. 确认数据是否都恢复正常

    3. 物理备份-XBK

    3-1. 安装XBK软件

    1. 安装依赖包:
    wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
    yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL libev
    2.  下载软件并安装
    wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.12/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.12-1.el7.x86_64.rpm
    3. yum -y install percona-xtrabackup-24-2.4.4-1.el7.x86_64.rpm

    3-2. innobackupex 使用

    3-2-1. 备份核心理念

    1. 针对非InnoDB,进行锁表备份,copy所有的非innoDB表文件
    2. 针对InnoDB表,立即触发CKPT,copy所有InnoDB表相关的文件(ibdata1,ibd,frm).
        并且将备份过程中产生,新的数据变化的部分redo一起备份走
    3. 在恢复时,xbk会调用InnoDB引擎的CSR过程,将数据和redo的LSN追平,然后进行一致性恢复.

    3-2-2. 基础备份过程

    (1) 全备
    [root@db01 backup]# innobackupex  --user=root --password=123 --no-timestamp /backup/full
    
    (2)增量备份
    innobackupex   --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/backup/full /backup/inc1 
    
    说明:
    --incremental    开关 
    --incremental-basedir=/backup/full 基于哪个备份进行增量
    /backup/inc1     增量备份的位置点
    (3) 利用全备进行恢复
    1. 
    [root@db01 ~]# pkill mysqld
    2. 
    [root@db01 ~]# 
    m -rf /data/mysql/data/*
    3. *****
    [root@db01 ~]# innobackupex --apply-log /backup/full/
    4. 
    [root@db01 full]# cp -a /backup/full/* /data/mysql/data/
    5. 
    [root@db01 full]# chown -R mysql.mysql /data/mysql/data/*
    6. 
    [root@db01 full]# /etc/init.d/mysqld start

    3-2-3. 备份产生的文件介绍

    (1) xtrabackup_binlog_info  
    
    记录备份时刻的二进制日志信息. 可以作为binlog截取的起点.
    
    (2) xtrabackup_checkpoints  
    
    from : 备份中包含的LSN号的起点,全备:0,增量:上次备份的结束位置
    to 	 : ckpt 时的LSN
    last-9 : 备份结束时的LSN.下次增量备份的起始位置.

    3-2-4. XBK 增量备份模拟

    1. 模拟数据
    create database test1 charset utf8mb4;
    use test1;
    create table t1 (id int);
    insert into t1 values(1),(2),(3);
    commit;
    1. 进行周日的全备
    [root@test02 inc1]# innobackupex --user=root --password=admin123 --port=3307 --datadir=/data/3307/data  --socket=/data/3307/mysql.sock --no-timestamp /backup/3307/full
    
    注意,因为是多实例安装的mysql,所以路径和端口和socket要指定
    1. 模拟周一的数据变化
    create database inc1 charset utf8mb4;
    use inc1;
    create table t1 (id int);
    insert into t1 values(1),(2),(3);
    commit;
    1. 进行周一的增量备份
    [root@test02 inc1]# innobackupex --user=root --password=admin123 --port=3307 --datadir=/data/3307/data  --socket=/data/3307/mysql.sock --no-timestamp --incremental --incremental-basedir=/backup/3307/full /backup/3307/inc1 
    
    说明:
    --incremental    开关 
    --incremental-basedir=/backup/full 基于哪个备份进行增量
    /backup/inc1     增量备份的位置点
    1. 检查备份的LSN
    [root@test02 3307]# cat full/xtrabackup_checkpoints 
    backup_type = full-backuped
    from_lsn = 0
    to_lsn = 168705090
    last_lsn = 168705099
    compact = 0
    recover_binlog_info = 0
    
    [root@test02 3307]# cat inc1/xtrabackup_checkpoints 
    backup_type = incremental
    from_lsn = 168705090
    to_lsn = 168711026
    last_lsn = 168711035
    compact = 0
    recover_binlog_info = 0
    1. 模拟周二数据变化
    create database inc2 charset utf8mb4;
    use inc2;
    create table t1 (id int);
    insert into t1 values(1),(2),(3);
    commit;
    1. 周二的增量
    innobackupex   --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/backup/inc1 /backup/inc2 
    1. 周三的数据变化
    create database inc3 charset utf8mb4;
    use inc3;
    create table t1 (id int);
    insert into t1 values(1),(2),(3);
    commit;
    1. 模拟上午10点数据库崩溃
    pkill mysqld 
    
    m -rf /data/mysql/data/*
    1. 恢复思路
    1. 停业务,挂维护页
    2. 查找可用备份并处理备份:full+inc1+inc2 
    3. binlog: inc2 到 故障时间点的binlog
    4. 恢复全备+增量+binlog
    5. 验证数据
    6. 起业务,撤维护页
    1. 恢复前的准备
    (1) 整理full
    
    innobackupex --user=root --password=admin123 --port=3307 --datadir=/data/3307/data  --socket=/data/3307/mysql.sock --no-timestamp --apply-log --redo-only /backup/3307/full
    
    (2) 合并inc1到full,并整理备份
    innobackupex --user=root --password=admin123 --port=3307 --datadir=/data/3307/data  --socket=/data/3307/mysql.sock --no-timestamp --apply-log --redo-only --incremental-dir=/backup/3307/inc1 /backup/3307/full
    
    (3) 合并inc2到full,并整理备份 
    innobackupex --user=root --password=admin123 --port=3307 --datadir=/data/3307/data  --socket=/data/3307/mysql.sock --no-timestamp --apply-log  --incremental-dir=/backup/3307/inc2 /backup/3307/full
    
    (4) 最后一次整理full
    innobackupex --user=root --password=admin123 --port=3307 --datadir=/data/3307/data  --socket=/data/3307/mysql.sock --no-timestamp --apply-log /backup/3307/full
    1. 截取二进制日志
    起点:
    [root@test02 inc2]# cat xtrabackup_binlog_info 
    mysql-bin.000005        3938    9f5d3fcf-e215-11ea-9d2c-001c42063d8f:1-42
    
    终点:
    SET @@SESSION.GTID_NEXT= '9f5d3fcf-e215-11ea-9d2c-001c42063d8f:45'/*!*/;
    
    [root@test02 binlog]# mysqlbinlog --skip-gtids --include-gtids='9f5d3fcf-e215-11ea-9d2c-001c42063d8f:43-45' mysql-bin.000005 >/backup/3307/bin.sql
    1. 恢复备份数据
    [root@db01 /]# cp -a  /backup/full/* /data/mysql/data/
    [root@db01 /]# chown -R mysql. /data/
    [root@db01 /]# /etc/init.d/mysqld start
    mysql> set sql_log_bin=0;
    mysql> source /backup/binlog.sql
    1. 验证数据
    mysql> select * from full.t1;
    mysql> select * from inc1.t1;
    mysql> select * from inc2.t1;
    mysql> select * from inc3.t1;

    3-3. 如果误删除的表只有10M,而备份有500G,该如何快速恢复误删除表?

    1. 在旧的数据库中找到t100w的建表语句
    mysql> show create table t100w;
    2. 在新的的MySQL创建一个库以及原来相同的结构的表
    mysql> CREATE TABLE `t100w` (... ...)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
    3. 将空表中的ibd文件删除
    mysql> alter table t100w discard tablespace;
    4. 将原表的ibd文件拷贝过来,并注意权限
      [root@test02 test01]# cp -a /data/3307/data/test01/t100w.ibd .
     5. 将原表的ibd文件进行导入
        mysql> alter table t100w import tablespace;  
    Query OK, 0 rows affected, 1 warning (0.72 sec)
    mysql> select count(*) from t100w;
    +----------+
    | count(*) |
    +----------+
    |  1030345 |
    +----------+

    3-4. 从mysqldump 全备中获取库和表的备份

    1、获得表结构
    # sed -e'/./{H;$!d;}' -e 'x;/CREATE TABLE `city`/!d;q'  full.sql>createtable.sql
    2、获得INSERT INTO 语句,用于数据的恢复
    # grep -i 'INSERT INTO `city`'  full.sqll >data.sql &
    3.获取单库的备份
    # sed -n '/^-- Current Database: `world`/,/^-- Current Database: `/p' all.sql >world.sql
  • 相关阅读:
    dayfunctools.weps 定义函数装饰器
    python3之concurrent.futures一个多线程多进程的直接对接模块,python3.2有线程池了
    python的类的super()
    django的admin
    python的单例模式
    git指南
    django创建验证码
    Django model对象接口
    Go语言基础
    迭代器&迭代对象&生成器
  • 原文地址:https://www.cnblogs.com/chacha51/p/13780077.html
Copyright © 2011-2022 走看看