Mysql——3、mysql备份和恢复

一、为什么要备份?

灾难恢复:硬件故障、软件故障、自然灾害、黑客攻击、误操作;
测试:
要注意的要点:
可容忍丢失多少数据;
恢复需要在多长时间内完成;
需要恢复哪些数据;
(1)做还原测试,用于测试备份的可用性;
(2)还原演练

二、备份类型

2.1 完全备份,部分备份:
完全备份:整个数据集
部分备份:仅备份其中的一张表或多张表;

2.2 完全备份,增量备份,差异备份
增量备份:仅备份最近一次完全备份或增量备份(如果存在增量)之后变化的数据部分;
差异备份:仅备份最近一次完全备份以来变化的数据;

2.3 热备份、温备份和冷备份:
热备份:在线备份,读写操作不受影响;
温备份:在线备份,读操作可继续进行,但写操作不允许;
冷备份:离线备份,数据库服务器离线,备份期间不能为业务提供读写服务;

MyISAM: 温备
InnoDB: 热备

2.4 物理备份和逻辑备份:
物理备份:直接复制数据文件进行的备份;
逻辑备份:从数据库中“导出”数据另存而进行的备份(与存储引擎无关);

2.5 规则备份时需要考虑的因素:
持锁的时长
备份过程时长
备份负载
恢复过程时长

三、备份什么?

数据、额外的数据(二进制日志和InnoDB的事务日志)、代码(存储过程和存储函数、触发器、事件调度器等)、服务器配置文件

3.1 设计备份方案:
数据集:完全备份+增量备份;
备份手段:物理备份、逻辑备份;

3.2 备份工具:
(1)mysqldump: 逻辑备份工具,适用于所有存储引擎,温备;完全备份,部分备份;对InnoDB存储引擎支持热备;
(2)cp, tar等文件系统工具:物理备份工具,适用于所有存储引擎;冷备;完全备份,部分备份;
(3)lvm2的快照:几乎热备;借助于文件系统管理工具实现物理备份;
(4)mysqlhotcopy: 几乎冷备;仅适用于MyISAM存储引擎;

3.3 备份工具的选择:
(1)mysqldump+复制binlog:
mysqldump:完全备份;
复制binlog中指定时间范围的event:通过备份二进制日志实现增量备份;
(2)lvm2快照+binlog:
lvm2快照:使用cp, tar等做物理备份,完全备份;
复制binlog中指定时间范围的event:增量备份;
(3)xtrabackup:
由Percona提供的支持对InnoDB做热备(物理备份)的工具,支持完全备份和增量备份
(4)对MyISAM引擎:温备,只支持完全备份

三、备份工具使用

逻辑备份工具:mysqldump, mydumper, phpMyAdmin
Schema和数据存储一起、巨大的SQL语句、单个巨大的备份文件
3.1 mysqldump
客户端命令,通过mysql协议连接至mysqld;
mysqldump [options] [db_name [tb1_name …]]
命令的语法格式:
mysqldump [OPTIONS] database [tables]:备份单个库,或库指定的一个或多个表
mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3…]:备份一个或多个库
mysqldump [OPTIONS] --all-databases [OPTIONS]:备份所有库
例如: mysqldump -uroot -P13506 -p --databases hellodb > /tmp/hellodb.sql

**3.2 MyISAM:**支持温备:不能热备,不能增备;锁定备份库,而后启动备份操作;
锁定方法:
–lock-all-tables:锁定所有库的所有表;
–lock-tables:对于每个单独的数据库,在启动备份之前锁定其所有表;
对InnoDB表一样生效,实现温备;
3.3 InnoDB:支持热备,增备:
–single-transaction 启动一个大的单一事务实现备份
-B, --databases db_name1 db_name2 …:备份指定的数据库
-C, --compress:压缩传输;
其它选项:
-E, --events:备份指定库的所有事件调度器;
-R, --routines:备份指定库的存储过程和存储函数;
–triggers:备份表相关的触发器
–master-data[=#]:
1:记录CHANGE MASTER TO语句;此语句未被注释;
2:记录为注释语句的CHANGE MASTER TO语句;
–flush-logs, -F:锁定表之后,执行flush logs命令;
注意:二进制日志文件与数据文件不应该放置于同一磁盘!!!

使用案例:小规模,每周完全备份,每日增量备份

使用一: 用mysqldump实现对指定数据库的备份;

#!bin/bash
cd /tmp
a=`date +%Y%m%d-%H%M%S`
#备份全部数据库的数据和结构
mysqldump -u数据用户名 -p数据库密码 --all-databases > backup-$a.sql
#备份全部数据库的结构(加 -d 参数)
#mysqldump -uroot -p123456 -A -d > /data/mydb.sql
#备份全部数据库的数据(加 -t 参数)
#mysqldump -uroot -p123456 -A -t > /data/mydb.sql

脚本示例:
1.首先设置各项参数,例如number最多需要备份的数目,备份路径,用户名,密码等。
2.执行mysqldump命令保存备份文件,并将操作打印至同目录下的log.txt中标记操作日志。
3.定义需要删除的文件:通过ls命令获取第九列,即文件名列,再通过head -1实现定义操作时间最晚的那个需要删除的文件。
4.定义备份数量:通过ls命令加上wc -l统计以sql结尾的文件的行数。
5.如果文件超出限制大小,就删除最早创建的sql文件

#!/bin/bash

#保存备份个数,备份31天数据
number=31
#备份保存路径
backup_dir=/root/mysqlbackup
#日期
dd=`date +%Y-%m-%d-%H-%M-%S`
#备份工具
tool=mysqldump
#用户名
username=root
#密码
password=TankB214
#将要备份的数据库
database_name=edoctor

#如果文件夹不存在则创建
if [ ! -d $backup_dir ]; 
then     
    mkdir -p $backup_dir; 
fi

#简单写法  mysqldump -u root -p123456 users > /root/mysqlbackup/users-$filename.sql
$tool -u $username -p$password $database_name > $backup_dir/$database_name-$dd.sql

#写创建备份日志
echo "create $backup_dir/$database_name-$dd.dupm" >> $backup_dir/log.txt

#找出需要删除的备份
delfile=`ls -l -crt  $backup_dir/*.sql | awk '{print $9 }' | head -1`

#判断现在的备份数量是否大于$number
count=`ls -l -crt  $backup_dir/*.sql | awk '{print $9 }' | wc -l`

if [ $count -gt $number ]
then
  #删除最早生成的备份,只保留number数量的备份
  rm $delfile
  #写删除文件日志
  echo "delete $delfile" >> $backup_dir/log.txt
fi

定期执行编写的定时任务脚本(记得先给shell脚本执行权限)

0 2 * * * /root/mysql_backup_script.sh

还原备份文件(第一种是在MySQL命令行中,第二种是使用SHELL行完成还原):

#1.在系统命令行中,输入如下实现还原:
mysql -uroot -p123456 < /data/mydb.sql
#2.在登录进入mysql系统中,通过source指令找到对应系统中的文件进行还原:
mysql> source /data/mydb.sql

使用二:实现利用binary logs完成增量备份;

首先在进行增量备份之前需要查看一下配置文件,查看 log_bin 是否开启,因为要做增量备份首先要开启 log_bin 。首先,进入到 myslq 命令行,输入如下命令:

show variables like '%log_bin%';

如下命令所示,则为未开启

mysql> show variables like '%log_bin%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| log_bin                         | OFF   |
| log_bin_basename                |       |
| log_bin_index                   |       |
| log_bin_trust_function_creators | OFF   |
| log_bin_use_v1_row_events       | OFF   |
| sql_log_bin                     | ON    |
+---------------------------------+-------+

修改 MySQL 配置项到如下代码段:vim /etc/mysql/mysql.conf.d/mysqld.cnf

# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
​
#
# The MySQL  Server configuration file.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
​
[mysqld]
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
datadir     = /var/lib/mysql
#log-error  = /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address   = 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
​
#binlog setting,开启增量备份的关键
log-bin=/var/lib/mysql/mysql-bin
server-id=123454

修改之后,重启 mysql 服务,输入:

show variables like '%log_bin%';

状态如下:

mysql> show variables like '%log_bin%';
+---------------------------------+--------------------------------+
| Variable_name                   | Value                          |
+---------------------------------+--------------------------------+
| log_bin                         | ON                             |
| log_bin_basename                | /var/lib/mysql/mysql-bin       |
| log_bin_index                   | /var/lib/mysql/mysql-bin.index |
| log_bin_trust_function_creators | OFF                            |
| log_bin_use_v1_row_events       | OFF                            |
| sql_log_bin                     | ON                             |
+---------------------------------+--------------------------------+

好了,做好了充足的准备,那我们就开始学习增量备份了。
查看当前使用的 mysql_bin.000*** 日志文件,

show master status;

状态如下:

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000015 |      610 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

当前正在记录日志的文件名为 mysql-bin.000015 。
当前数据库中有如下数据:

mysql> select * from users;
+-------+------+----+
| name  | sex  | id |
+-------+------+----+
| zone  | 0    |  1 |
| zone1 | 1    |  2 |
| zone2 | 0    |  3 |
+-------+------+----+

我们插入一条数据:

insert into `zone`.`users` ( `name`, `sex`, `id`) values ( 'zone3', '0', '4');

查看效果:

mysql> select * from users;
+-------+------+----+
| name  | sex  | id |
+-------+------+----+
| zone  | 0    |  1 |
| zone1 | 1    |  2 |
| zone2 | 0    |  3 |
| zone3 | 0    |  4 |
+-------+------+----+

我们执行如下命令,使用新的日志文件:

mysqladmin -uroot -123456 flush-logs

日志文件从 mysql-bin.000015 变为 mysql-bin.000016,而 mysql-bin.000015 则记录着刚刚 insert 命令的日志。上句代码的效果如下:

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000016 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

那么到现在为止,其实已经完成了增量备份了。
恢复增量备份
那么现在将刚刚插入的数据删除,效果如下:

delete from `zone`.`users` where `id`='4' 
mysql> select * from users;
+-------+------+----+
| name  | sex  | id |
+-------+------+----+
| zone  | 0    |  1 |
| zone1 | 1    |  2 |
| zone2 | 0    |  3 |
+-------+------+----+

那么现在就是重点时间了,从 mysql-bin.000015 中恢复数据:

mysqlbinlog /var/lib/mysql/mysql-bin.000015 | mysql -uroot -p123456 zone;

上一句代码指定了,需要恢复的 mysql_bin 文件,指定了用户名:root 、密码:123456 、数据库名:zone。效果如下:

mysql> select * from users;
+-------+------+----+
| name  | sex  | id |
+-------+------+----+
| zone  | 0    |  1 |
| zone1 | 1    |  2 |
| zone2 | 0    |  3 |
| zone3 | 0    |  4 |
+-------+------+----+

OK,整一个增量备份的操作流程都在这里了,那么我们如何将它写成脚本文件呢,代码如下:

#!/bin/bash
#在使用之前,请提前创建以下各个目录
BakDir=/usr/local/work/backup/daily
#增量备份时复制mysql-bin.00000*的目标目录,提前手动创建这个目录
BinDir=/var/lib/mysql
#mysql的数据目录
LogFile=/usr/local/work/backup/bak.log
BinFile=/var/lib/mysql/mysql-bin.index
#mysql的index文件路径,放在数据目录下的
​
mysqladmin -uroot -p123456 flush-logs

#这个是用于产生新的mysql-bin.00000*文件
# wc -l 统计行数
# awk 简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
Counter=`wc -l $BinFile |awk '{print $1}'`
NextNum=0
#这个for循环用于比对$Counter,$NextNum这两个值来确定文件是不是存在或最新的
for file in `cat $BinFile`
do
    base=`basename $file`
    echo $base
    #basename用于截取mysql-bin.00000*文件名,去掉./mysql-bin.000005前面的./
    NextNum=`expr $NextNum + 1`
    if [ $NextNum -eq $Counter ]
    then
        echo $base skip! >> $LogFile
    else
        dest=$BakDir/$base
        if(test -e $dest)
        #test -e用于检测目标文件是否存在,存在就写exist!到$LogFile去
        then
            echo $base exist! >> $LogFile
        else
            cp $BinDir/$base $BakDir
            echo $base copying >> $LogFile
         fi
     fi
done
echo `date +"%Y年%m月%d日 %H:%M:%S"` $Next Bakup succ! >> $LogFile

四、物理备份:数据文件的时间一致性?

基于lvm2快照+cp(tar)的备份

1、请求锁定所有表:

mysql> FLUSH TABLES WITH READ LOCK;

2、记录二进制日志文件及事件位置:

mysql> SHOW MASTER STATUS;
mysql -e 'SHOW MASTER STATUS' > /PATH/TO/SOMEFILE

3、创建快照:
lvcreate -L SIZE -s -p r -n NAME /dev/VG_NAME/LV_NAME
如:

lvcreate -L 2G -s -n  mydata-snap -p r /dev/myvg/mydata
mke2fs -t ext4 /dev/myvg/mydata-snap
mount /dev/myvg/mydata-snap /data
mkdir -v /data/{mysql,binlogs}
chown -R mysql.mysql /data/*

修改/etc/my.cnf.d/server.conf的二进制日志存放位置:log_bin=/data/binlogs/mysql-bin
启动数据库systemctl start mariadb
4、释放锁:

mysql> UNLOCK TABLES

5、挂载快照卷,复制数据进行备份;
cp, rsync, tar等命令复制数据;
6、备份完成之后,删除快照卷;

mysql> SET SESSION sql_log_bin=0;
mysql> SOURCE /path/from/somefile.sql;
mysql> SET SESSION sql_log_bin=1;

mysql> FLUSH TABLES WITH READ LOCK;
mysql> FLUSH LOGS;

7、制定好策略,通过原卷备份二进制日志

mysql -e 'SHOW MASTER STATUS';> /root/pos-`date +%F`

五、Xtrabackup(MySQL 数据库物理热备的备份工具)

www.percona.com
下载地址:https://www.percona.com/downloads/XtraBackup/LATEST/
innobackupex: 客户端工具, 以mysql协议连入mysqld,不支持离线备份

完整备份策略:完整备份 + 增量备份 + 二进制日志

注意:
1、将数据和二进制文件放置于不同的设备;二进制日志也应该周期性地备份;
2、将数据和备份分开存放,建议不在同一设备、同一主机、同一机房、同一地域;
3、每次灾难恢复后都应该立即做一次完全备份;
4、备份后的数据应该周期性地做还原测试;

从备份中恢复应该遵循的步骤:
1、停止MySQL服务器;
2、记录服务器配置和文件权限;
3、将备份恢复到MySQL数据目录;此步骤依赖具体的备份工具;
4、改变配置和文件权限;
5、以限制方式启动MySQL服务器:比如通过网络访问;
[mysqld]
skip-networking
socket=/tmp/mysql-recovery.sock
6、载入额外的逻辑备份;而检查和重放二进制日志;
7、检查已经还原的数据;
8、以完全访问模式重启服务器;

其它的备份工具:
	SELECT ... INTO OUTFILE ''
	LOAD FILE 

	mylvmbackup

猜你喜欢

转载自blog.csdn.net/change_can/article/details/85237798