一、前言
备份与恢复无疑是学习mysql不可或缺的一项技能,有段子说从入门到放弃,从删库到跑路,如果一个应用存储着大量的业务数据,没有进行定期备份的话,一旦出现一些不可抗力因素,硬件故障,用户误删除数据等造成数据丢失,将会造成整个系统瘫痪,重则导致公司倒闭,这时如果你定期备份数据并且及时恢复数据,对于老板而言,你的功劳绝不亚于拯救世界。这里我们只分析常见的,像MySQL Enterprise Backup 这种企业版 ,MyISAM这种引擎等,以后有机会再分析。
二、备份基础知识
2.1 根据文件方式
从大体上我们分为逻辑备份(比如mysqldump)和物理备份|(直接拷贝文件)
1):逻辑备份:
mysqldump(MDP)
replication
优点
- 不需要下载安装,mysql官方自带
- 可移植性高,文件直接导出SQL语句,语句可直接适用于其他SQL服务器;
- 在数据恢复之前可增加、修改数据;
- 数据恢复粒度小可以是服务器、数据库、表级别;
- 使用文本格式,可读性高;
- 压缩比较高,节省备份的磁盘空间
缺点
备份时需要访问mysql服务器,影响其他客户端;
需要将数据转换成逻辑格式(SQL,CSV);
如果命令运行在客户端,mysql服务器还需要将数据发送给客户端;
因为输出格式为文本文件,占用空间较大;
依赖于数据库引擎,需要从磁盘把数据读出,然后转换成SQL进行转储,比较耗费资源,数据量大的话效率较低
2):物理备份:
MySQL Enterprise Backup(企业版)
percona xtrabackup(PBK,XBK)
优点
- 完整的Mysql文件和目录备份,只需要复制文件不需要转换,速度比逻辑备份更快;
- 除了备份数据,还能备份配置文件和日志文件;
- 不需要运行Mysql服务器就可以完成备份;
- 备份工具简单使用cp、scp、tar命令即可完成备份;
缺点
- 可移植性不高,恢复数据只适用于相同或类似的机器上;
- 为了保持数据库文件的一致性,需要停机备份;
- 恢复粒度不能按表或用户恢复;
- 可读性差
- 压缩率低
2.2 根据数据库的运行状态,我们可分为3种
1):热备份
- 备份不需要停机,可读可写(只读不写,其实还可以又细分为温备份,这里不做分析);
- 业务正常
2):温备份
- 备份不需要停停机,需要加写锁,或者设置read_only;
- 业务只读不写
3):冷备份
- 关机情况下;关闭数据库业务,数据库没有任何变更的情况下,进行备份数据.
- 业务停止
2.3 备份策略:
1):全量备份:
2):增量备份:
三、备份操作
3.1:mysqldump工具的使用
连接mysql方式:
#-u(用户名) -p(密码) -S(socker套接字文件) -h(ip) -P(端口)
#本地备份:
mysqldump -uroot -p -S /tmp/mysql.sock
#远程备份:
mysqldump -uroot -p -h 10.0.0.51 -P8001
1. 备份所有数据库
若想用mysqldump备份整个实例,可以使用 --all-databases 或 -A 参数:
root@6fcbb41f6f2a:/data# mysqldump -uroot -p --all-databases > /data/backup/all_database.sql
如果需要压缩的话
mysqldump -uroot -p --master-data=2 --single-transaction -A | gzip > /data/backup/all_database.sql.gz
2. 备份部分数据库
有的时候我们会遇到只需要备份某些库的需求,这个时候我们就可以使用 --databases 或 -B参数了,该参数后面跟数据库名称,多个数据库间用空格隔开。
eg:备份neti mysql 数据库:mysqldump -uroot -p --databases neti mysql > /data/backup/neti.sql
root@6fcbb41f6f2a:/tmp# mysqldump -uroot -p --databases neti> /data/backup/neti.sql
3.备份部分表
其中neti是数据库 t_usert_shop 是数据表
单表:
root@6fcbb41f6f2a:/tmp# mysqldump -uroot -p neti t_user >/data/backup/t_user.sql
多表:
root@6fcbb41f6f2a:/tmp# mysqldump -uroot -p neti t_user t_shop >/data/backup/neti_tb.sql
单表加 表中字段条件:
root@6fcbb41f6f2a:/tmp# mysqldump -uroot -p neti t_user --where=" create_time >= '2019-08-01 00:00:00' " > /tmp/t_user_create_time.sql
4 .参数解析
1):只备份结构: --no-data 简写为 -d 选项;
root@6fcbb41f6f2a:/tmp# mysqldump -uroot -p neti --no-data > /data/backup/neti_no_data.sql
2):只备份数据 --no-create-info 简写为 -t 选项。
root@6fcbb41f6f2a:/tmp# mysqldump -uroot -p neti --no-create-info > /data/backup/neti_no_data.sql
3):备份存储过程 --routines 简写为 -R 选项。备份函数 --events 简写为 -E 选项。
mysqldump -uroot -pxxxxxx -R -E --databases testdb > /data/backup/testdb.sql
4):以事务的形式备份
如果我们想在dump过程中保证数据的一致性,减少锁表,则可以用 --single-transaction 选项,这个选项对InnoDB的数据表很有用,且不会锁表。
mysqldump -uroot -pxxxxxx --single-transaction --databases testdb > /data/backup/testdb.sql
5):以事务的形式备份-F 在备份开始时,刷新一个新binlog日志
6):master-data
功能:
- 备份是自动记录日志
- 自动解表和锁表
- 配合single transaction 可以减少锁表时间
mysqldump -uroot -p -A -R --triggers --master-data=2 >/data/backup/world.sql
[root@db01 ~]# grep 'CHANGE' /backup/world.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000035', MASTER_LOG_POS=194;
功能:
(1)在备份时,会自动记录,二进制日志文件名和位置号
0 默认值
1 以change master to命令形式,可以用作主从复制
2 以注释的形式记录,备份时刻的文件名+postion号
(2) 自动锁表
(3)如果配合--single-transaction,只对非InnoDB表进行锁表备份,InnoDB表进行“热“”备,实际上是实现快照备份。
7): --single-transaction
innodb 存储引擎开启热备(快照备份)功能
master-data可以自动加锁
(1)在不加--single-transaction ,启动所有表的温备份,所有表都锁定
(1)加上--single-transaction ,对innodb进行快照备份,对非innodb表可以实现自动锁表功能
例子6: 备份必加参数
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=OFF >/data/backup/full.sql
8) --set-gtid-purged=auto
auto , on
off
使用场景:
1. --set-gtid-purged=OFF,可以使用在日常备份参数中.
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=OFF >/data/backup/full.sql
2. auto , on:在构建主从复制环境时需要的参数配置
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=ON >/data/backup/full.sql
9)--max-allowed-packet=#
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=OFF --max-allowed-packet=256M >/data/backup/full.sql
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=OFF --max-allowed-packet=256M neti>/data/backup/full.sql
--max-allowed-packet=64M
The maximum packet length to send to or receive from server.
mysqldump -uroot -P8001 -h47.98.137.146 -p -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=OFF --max-allowed-packet=256M --databases neti>./full.sql
mysqldump -h47.98.137.146 -uroot -p123456 -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=OFF --max-allowed-packet=256M --databases neti >/data/backup/mysql/neti_20200421-151905.sql
3.6:增量备份
其实就是备份binlog文件
3.6:恢复
1):全量恢复
mysql -uroot -p < /data/backup/all_database.sql
四、脚本备份
linux脚本一般用.sh来结尾的
1):编写脚本
增量备份:
创建mysqlback.sh
date_now=$(date "+%Y%m%d-%H%M%S")
backUpFolder=/data/backup/mysql
host='47.98.137.146'
username="root"
password="123456"
db_name="neti"
port=8001
#定义备份文件名
fileName="${db_name}_${date_now}.sql"
#定义备份文件目录
backUpFileName="${backUpFolder}/${fileName}"
echo "starting backup mysql ${db_name} at ${date_now}."
mysqldump -h${host} -u${username} -p${password} -P${port} -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=OFF --max-allowed-packet=256M --databases ${db_name} >${backUpFileName}
#进入到备份文件目录
cd ${backUpFolder}
#压缩备份文件
tar zcvf ${fileName}.tar.gz ${fileName}
增量备份脚本mysqlIncreamBackup.sh
#!/bin/bash
#在使用之前,请提前创建以下各个目录
backupDir=/data/backup/mysql/daily
#增量备份时复制mysql-bin.00000*的目标目录,提前手动创建这个目录
mysqlDir=/data/mysql
#mysql的数据目录
logFile=/data/backup/mysql/log/bak.log
BinFile=/data/mysql/mysql-bin.index
#mysql的index文件路径,放在数据目录下的
host='47.98.137.146'
username="root"
password="123456"
port=8001
containerid='6fcbb41f6f2a'
mysqladmin -h${host} -u${username} -p${password} -P${port} 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=$backupDir/$base
if(test -e $dest)
#test -e用于检测目标文件是否存在,存在就写exist!到$logFile去
then
echo $base exist! >> $logFile
else
docker cp $containerid:$mysqlDir/$base $backupDir
#cp $mysqlDir/$base $backupDir
echo $base copying >> $logFile
fi
fi
done
echo `date +"%Y年%m月%d日 %H:%M:%S"` $Next Bakup succ! >> $logFile
2):执行脚本
第一种(这种办法需要用chmod使得文件具备执行条件(x): chmod u+x datelog.sh):
chmod u+x mysqlback.sh
./mysqlback.sh
第二种(这种办法不需要文件具备可执行的权限也可运行):
sh datelog.sh
第三种加入系统定时器
定时任务操作
crontab -u //设定某个用户的cron服务
crontab -l //列出某个用户cron服务的详细内容
crontab -r //删除某个用户的cron服务
crontab -e //编辑某个用户的cron服务
crontab -i //打印提示,输入yes等确认信息
我们将 crontab -e增加
0 0 * * * sh /disk/mysqlbackup.sh
参数解析
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
定时任务的每段为:分,时,日,月,周,用户,命令
第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令
*:表示任意时间都,实际上就是“每”的意思。可以代表00-23小时或者00-12每月或者00-59分
-:表示区间,是一个范围,00 17-19 * * * cmd,就是每天17,18,19点的整点执行命令
,:是分割时段,30 3,19,21 * * * cmd,就是每天凌晨3和晚上19,21点的半点时刻执行命令
/n:表示分割,可以看成除法,*/5 * * * * cmd,每隔五分钟执行一次
文章部分内容参考:Mysql备份还有这么多套路,还不了解下?