一、为什么要备份?
灾难恢复:硬件故障、软件故障、自然灾害、黑客攻击、误操作;
测试:
要注意的要点:
可容忍丢失多少数据;
恢复需要在多长时间内完成;
需要恢复哪些数据;
(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