• linux运维、架构之路-MySQL备份与恢复(四)


    一、备份方式

    ①逻辑备份(文件表示:SQL语句)

    ②物理备份(数据文件的二进制副本)

    ③基于快照的备份

    ④基于复制的备份

    二、备份工具

    ①mysqldump:原生自带的逻辑备份工具

    ②mysqlbinlog:实现binlog备份的原生态命令

    ③xtrabackup:precona公司开发的性能很高的物理备份工具

    三、Mysqldump

    1、常用参数

    -A, --all-databases      #备份所有库
    -B 增加建库(create)及"use库"的语句,可以接多个库名,同时备份多个库
    -B 库1 库2
    -d                       #仅备份表结构
    -t                       #仅备份数据
    --compact                #减少无用数据输出(调试)
    -R, --routines	         #备份存储过程和函数数据
       --triggers	         #备份触发器数据
    -F,--flush-logs         #刷新binlog日志
    --master-data=1|2        #告诉备份时刻的binlog位置
    -x, --lock-all-tables    #锁所有备份表
    -l,  --lock-tables       #锁单表
    

    2、参数使用详解

    ①全库备份

    mysqldump -uroot -p123456 -A >/backup/full.sql

    ②备份多个库

    mysqldump -uroot -p123456 -B oldboy oldgirl>/backup/oldboy_oldgirl.sql

    ③分库备份

    for name in `mysql -uroot -p123456 -e "show databases;"|sed 1d`
    do
     mysqldump -uroot -p'123456' -B $name
    done

    ④单表备份

    mysqldump -uroot -p123456 oldboy test>/backup/oldboy_test.sql

    ⑤多表备份

    mysqldump -uroot -p123456 oldboy 表1 表2 表3 …… /backup/oldboy_test.sql

    ⑥分库分表备份

    #!/bin/sh
    Myuser=root
    Mypass=123456
    Mycmd="mysql -u$Myuser -p$Mypass"
    Mydump="mysqldump -u$Myuser -p$Mypass -x -F -R"
    Dblist=`$Mycmd -e "show databases;"|sed '1,2d'|egrep -v "_schema|mysql"`
    for database in $Dblist
    do
      Tablist=`$Mycmd -e "show tables from $database;"|sed 1d`
      for table in $Tablist
      do
      mkdir -p /tmp/${database}
      $Mydump $database $table|gzip >/tmp/${database}/${table}_$(date +%F).sql.gz
      done
    done

    ⑦压缩备份

    mysqldump -uroot -p123456  -B --master-data=2 oldboy|gzip >/backup/oldboy.sql.gz

    ⑧innodb引擎备份命令

    mysqldump -uroot -p123456 -A -B -R --triggers --master-data=2 --single-transaction|gzip >/backup/all.sql.gz

    ⑨适合多引擎混合备份

    mysqldump -uroot -p123456 -A -B -R --triggers --master-data=2|gzip >/backup/alL_$(date +%F).sql.gz

    3、mysqldump备份恢复实战案例

    ===================================================

    环境:正在运行的网站,mysql数据库,数据量25G,日业务增量10-15M

    [root@db ~]# cat /etc/redhat-release 
    CentOS release 6.9 (Final)
    [root@db ~]# uname -r
    2.6.32-696.el6.x86_64
    [root@db ~]# getenforce 
    Disabled
    [root@db ~]# hostname -I
    172.19.5.56 172.16.1.56
    [root@db ~]# mysql -V
    mysql  Ver 14.14 Distrib 5.6.36, for linux-glibc2.5 (x86_64) using  EditLine wrapper

    备份方式:每天晚上00:00,计划任务调用mysqldump执行全备脚本

    mysqldump -uroot -p123456 -A -B -R --triggers --master-data=2 |gzip >/backup/all_$(date +%F_%T).sql.gz

    故障时间点:第二天上午10点,某开发人员误删除了一个表

    如何恢复?

    =====================================================

    解题思路:

    1、使用测试库,恢复全备 source
    2、恢复从00:00到10点之间的binlog
        a.截取00:00到10点这段 binlog在测试库恢复
        b.导出删除表
    3、将删除的表进行恢复到生产库

    ①模拟数据

    create database oldboy;#创建oldboy库
    use oldboy;
    create table test( id int(4) not null,name char(20) not null);#在oldboy库中创建test表
    insert into test values(1,"oldboy");#test表中插入数据
    insert into test values(2,"oldgirl");
    insert into test values(3,"inca");
    insert into test values(4,"zuma");
    insert into test values(5,"kaka");
    insert into test values(6,"老男孩");
    mysql> select * from oldboy.test;
    +----+-----------+
    | id | name      |
    +----+-----------+
    |  1 | oldboy    |
    |  2 | oldgirl   |
    |  3 | inca      |
    |  4 | zuma      |
    |  5 | kaka      |
    |  6 | 老男孩    |
    +----+-----------+

    ②模拟全备之后增量数据

    mysql -e "use oldboy;insert into test values(7,'bingbing');"
    mysql -e "use oldboy;insert into test values(8,'xiaoting');"
    mysql -e "select * from oldboy.test;"
    +----+-----------+
    | id | name      |
    +----+-----------+
    |  1 | oldboy    |
    |  2 | oldgirl   |
    |  3 | inca      |
    |  4 | zuma      |
    |  5 | kaka      |
    |  6 | 老男孩    |
    |  7 | bingbing  |
    |  8 | xiaoting  |
    +----+-----------+

    ③误删除数据

    [root@db ~]# date -s "2018/01/23 10:00"
    mysql> use oldboy;
    Database changed
    mysql> drop table test;
    mysql> show tables;
    Empty set (0.00 sec)

    ④开始恢复准备

    iptables -I INPUT -p tcp --dport 3306 ! -s 172.19.5.56 -j DROP #非172.19.5.56禁止访问数据库3306端口

    收集恢复所需数据

    cp -a /data/mysql/mysql-bin.* /backup/   #copy所有的binlog日志到/backup下面,binlog指定在哪里看配置文件即可
    gzip -d all_2018-01-22_00:00:05.sql.gz #解压晚上00:00点的全备
    [root@db backup]# sed -n '22p' all_2018-01-22_00:00:05.sql #提取出binlog位置点
    -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=658960;
    mysqlbinlog -d oldboy --start-position=658960 mysql-bin.000002 -r bin.sql #截取binlog位置点 [root@db backup]# ll
    /backup/ #收集到最终全备及增量恢复所需的数据 total 1952 -rw-r--r-- 1 root root 656383 2018-01-22 00:00 all_2018-01-22_00:00:05.sql -rw-rw---- 1 root root 9864 2018-01-23 09:17 bin.sql -rw-rw---- 1 mysql mysql 143 2018-01-22 10:54 mysql-bin.000001 -rw-rw---- 1 mysql mysql 1317215 2018-01-23 09:02 mysql-bin.000002

    ⑤恢复全备

    mysql <all_2018-01-22_00:00:05.sql
    [root@db backup]# mysql -e "select * from oldboy.test;"
    +----+-----------+
    | id | name      |
    +----+-----------+
    |  1 | oldboy    |
    |  2 | oldgirl   |
    |  3 | inca      |
    |  4 | zuma      |
    |  5 | kaka      |
    |  6 | 老男孩    |
    +----+-----------+

    ⑥恢复增量数据

    [root@db backup]# mysql<bin.sql 
    [root@db backup]# mysql -e "select * from oldboy.test;"
    +----+-----------+
    | id | name      |
    +----+-----------+
    |  1 | oldboy    |
    |  2 | oldgirl   |
    |  3 | inca      |
    |  4 | zuma      |
    |  5 | kaka      |
    |  6 | 老男孩    |
    |  7 | bingbing  |
    |  8 | xiaoting  |
    +----+-----------+

    恢复数据完毕,调整iptables允许用户访问,截取多个binlog问题

    mysqlbinlog -d oldboy --start-position=339 mysql-bin.000001 mysql-bin.0000002 -r bin.sql

    四、XtraBackup

    xtrabackup:是一款基于InnoDB的在线热备工具,具有开源,免费,支持在线热备,占用磁盘空间小,能够非常快速地备份与恢复mysql数据库,(备份时不影响数据读写)

    1、工作原理

    2、安装部署

    ①添加yum源安装依赖

    wget -O /etc/yum.repos.d/epel.repo  http://mirrors.aliyun.com/repo/epel-6.repo
    yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL

     ②下载安装xtrabackup

    wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.4/binary/redhat/6/x86_64/percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm
    yum -y install percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm

    3、XtraBackup备份恢复实战

    ①全备

    innobackupex --no-timestamp /backup/full

    由于备份命令依赖于/etc/my.cnf文件中basedir  datadir  socket,如配置文件中未配置,需在命令行指定

    [client]
    user = root
    password = 123456
    
    [mysqld]
    log-bin=/data/mysql/mysql-bin
    character-set-server = utf8
    basedir = /application/mysql/
    datadir = /application/mysql/data/
    port = 3306
    socket = /tmp/mysql.sock

    ②应用日志到全备中(预处理数据)

    innobackupex --apply-log /backup/full/

    ③模拟数据损坏

    rm -fr /application/mysql/data/*
    pkill mysql

    ④恢复全备数据

    innobackupex --copy-back /backup/full/
    chown -R mysql.mysql /application/mysql-5.6.36/ #这里重新授权注意一下,有时候发现授权软链接不管用

    ⑤查看恢复结果

    [root@db ~]# mysql -e "select * from oldboy.test;"
    +----+-----------+
    | id | name      |
    +----+-----------+
    |  1 | oldboy    |
    |  2 | oldgirl   |
    |  3 | inca      |
    |  4 | zuma      |
    |  5 | kaka      |
    |  6 | 老男孩    |
    |  7 | bingbing  |
    |  8 | xiaoting  |
    +----+-----------+

    innobackupex命令常用参数说明

    --defaults-file
    #指明服务器的配置文件,此参数必须作为innobackupex的第一个参数,否则报错
    --user        #备份的用户名
    --password    #指明备份用户名的密码
    /backup       #备份的目录
    --apply-log   #指明为重做日志
    --copy-back   #指明为恢复
    --slave-info
    #备份从库的show slave status信息,仅用于在备份从库时使用
    --no-lock
    #不锁表,仅适用于存储引擎为innodb,并且不在乎备份位置点时使用
    --no-timestamp#不按时间生成备份目录
    

    4、XtraBackup增量备份恢复实战

    =================================================

    场景:xtrabackup全备+增量

    备份策略:定时任务周日晚上00点全备,周一到周六都是基于上一天的增量备份

    故障场景:周三的时候,下午两点,某开发小菜鸟误删除了一张test表,大于2G

    解决思路:

    ①准备上周日全备,并--apply-log --redo-only
    ②合并增量,周一 、周二 --apply-log --redo-only 周三 --apply-log
    ③在测试库恢复以上数据,数据的目前状态应该周三凌晨1:00
    ④需要恢复的数据状态是,下午2点钟左右,删除test表之前的数据状态,从1点开始的binlog恢复到删除之前的那个events的position
    ⑤导出删除的表test,恢复到生产库,验证数据可用性、完整性。
    ⑥启动应用连接数据库

    ==================================================

    ①模拟案例

    mkdir /backup/inc{1,2} -p #创建增量备份的目录
    innobackupex --no-timestamp /backup/full/ #周日全备
    
    #模拟插入数据#
    insert into test values(9,'outman');
    insert into test values(10,'man');

    ②周一增量备份

    innobackupex --incremental --no-timestamp --incremental-basedir=/backup/full/ /backup/inc1

    ③再次模拟插入数据

    insert into test values(11,'110');
    insert into test values(12,'120');

    ④周二增量备份

    innobackupex --incremental --no-timestamp --incremental-basedir=/backup/inc1 /backup/inc2

    ⑤再次模拟数据变化

    insert into test values(130,'newdata1');
    insert into test values(140,'newdata2');

    此时表中内容为

    mysql> select * from test;
    +-----+-----------+
    | id  | name      |
    +-----+-----------+
    |   1 | oldboy    |
    |   2 | oldgirl   |
    |   3 | inca      |
    |   4 | zuma      |
    |   5 | kaka      |
    |   6 | 老男孩    |
    |   7 | bingbing  |
    |   8 | xiaoting  |
    |   9 | outman    |
    |  10 | man       |
    |  11 | 110       |
    |  12 | 120       |
    | 130 | newdata1  |
    | 140 | newdata2  |
    +-----+-----------+
    14 rows in set (0.00 sec)

    ⑥故障场景模拟:下午2点误删除test表

    mysql> use oldboy;
    Database changed
    mysql> drop table test;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> select * from test;
    ERROR 1146 (42S02): Table 'oldboy.test' doesn't exist

    故障恢复:

    ①全备进行apply-log,暂时不需要undo回滚,只做redo

    innobackupex --apply-log --redo-only /backup/full

    ②将周一的inc1合并到全备当中去,暂时不需要undo回滚,只做redo

    innobackupex --apply-log --redo-only --incremental-dir=/backup/inc1 /backup/full

    ③将周二的inc2合并到全备当中去,undo和redo都apply

    innobackupex --apply-log --incremental-dir=/backup/inc2 /backup/full

    ④最终把所有合并后的备份集合做apply

    innobackupex --apply-log /backup/full

    ⑤截取周二增量备份inc2之后产生的binlog,截取到delete之前,即可恢复故障

    确认binlog起点

    [root@db ~]# cat /backup/inc2/xtrabackup_binlog_info
    mysql-bin.000017    1022

    截取drop操作之前的binlog

    mysqlbinlog --start-position=1022 --stop-position=1484 /data/mysql/mysql-bin.000017 >/backup/incbinlog.sql

    使用命令查看binlog的event

    mysql> show binlog events in 'mysql-bin.000017';
    +------------------+------+-------------+-----------+-------------+-----------------------------------------------------------+
    | Log_name         | Pos  | Event_type  | Server_id | End_log_pos | Info                                                      |
    +------------------+------+-------------+-----------+-------------+-----------------------------------------------------------+
    | mysql-bin.000017 |    4 | Format_desc |         1 |         120 | Server ver: 5.6.36-log, Binlog ver: 4                     |
    | mysql-bin.000017 |  120 | Query       |         1 |         203 | BEGIN                                                     |
    | mysql-bin.000017 |  203 | Query       |         1 |         316 | use `oldboy`; insert into test values(9,'outman')         |
    | mysql-bin.000017 |  316 | Xid         |         1 |         347 | COMMIT /* xid=37 */                                       |
    | mysql-bin.000017 |  347 | Query       |         1 |         430 | BEGIN                                                     |
    | mysql-bin.000017 |  430 | Query       |         1 |         541 | use `oldboy`; insert into test values(10,'man')           |
    | mysql-bin.000017 |  541 | Xid         |         1 |         572 | COMMIT /* xid=38 */                                       |
    | mysql-bin.000017 |  572 | Query       |         1 |         655 | BEGIN                                                     |
    | mysql-bin.000017 |  655 | Query       |         1 |         766 | use `oldboy`; insert into test values(11,'110')           |
    | mysql-bin.000017 |  766 | Xid         |         1 |         797 | COMMIT /* xid=57 */                                       |
    | mysql-bin.000017 |  797 | Query       |         1 |         880 | BEGIN                                                     |
    | mysql-bin.000017 |  880 | Query       |         1 |         991 | use `oldboy`; insert into test values(12,'120')           |
    | mysql-bin.000017 |  991 | Xid         |         1 |        1022 | COMMIT /* xid=58 */                                       |
    | mysql-bin.000017 | 1022 | Query       |         1 |        1105 | BEGIN                                                     |
    | mysql-bin.000017 | 1105 | Query       |         1 |        1222 | use `oldboy`; insert into test values(130,'newdata1')     |
    | mysql-bin.000017 | 1222 | Xid         |         1 |        1253 | COMMIT /* xid=77 */                                       |
    | mysql-bin.000017 | 1253 | Query       |         1 |        1336 | BEGIN                                                     |
    | mysql-bin.000017 | 1336 | Query       |         1 |        1453 | use `oldboy`; insert into test values(140,'newdata2')     |
    | mysql-bin.000017 | 1453 | Xid         |         1 |        1484 | COMMIT /* xid=78 */                                       |
    | mysql-bin.000017 | 1484 | Query       |         1 |        1605 | use `oldboy`; DROP TABLE `test` /* generated by server */ |
    +------------------+------+-------------+-----------+-------------+-----------------------------------------------------------+
    20 rows in set (0.00 sec)

    停库,备份binlog日志,本实例中binlog日志单独存放在/data/mysql目录下,无需备份

    [root@db ~]# /etc/init.d/mysqld stop
    Shutting down MySQL.. SUCCESS! 
    [root@db ~]# rm -fr /application/mysql/data/*

    恢复xtrabackup数据

    innobackupex --copy-back /backup/full/
    chown -R mysql.mysql /application/mysql-5.6.36/
    /etc/init.d/mysqld start

    恢复binlog

    mysql> set sql_log_bin=0; #临时不记录binlog
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> source /backup/incbinlog.sql
    Query OK, 0 rows affected (0.00 sec)

    ⑥故障恢复完毕

    mysql> select * from oldboy.test;
    +-----+-----------+
    | id  | name      |
    +-----+-----------+
    |   1 | oldboy    |
    |   2 | oldgirl   |
    |   3 | inca      |
    |   4 | zuma      |
    |   5 | kaka      |
    |   6 | 老男孩    |
    |   7 | bingbing  |
    |   8 | xiaoting  |
    |   9 | outman    |
    |  10 | man       |
    |  11 | 110       |
    |  12 | 120       |
    | 130 | newdata1  |
    | 140 | newdata2  |
    +-----+-----------+
    14 rows in set (0.00 sec)
    成功最有效的方法就是向有经验的人学习!
  • 相关阅读:
    在C#中实现Python的分片技术
    如何将松散的dll打包进需要发布的exe
    Python基础学习(第8天)
    javascript中 的 + RegExp['x241'] 怎么理解
    CSS和JavaScript标签style属性对照表
    浏览器 怪异模式(Quirks Mode) 与 标准模式(Standards Mode)
    Javascript如何判断一个变量是数字类型?
    我的第一个jquery插件:下拉多选框
    javascript中===与==
    ztree高级实例(原创)
  • 原文地址:https://www.cnblogs.com/yanxinjiang/p/8328575.html
Copyright © 2020-2023  润新知