1 数据库备份的分类
1.1 数据备份重要性
在生产环境中,数据的安全性至关重要,任何数据的丢失都可能产生严重的后果。造成数据丢失的原因包括:
- 程序错误
- 人为操作失误
- 运算错误
- 磁盘故障
- 灾难(如火灾、地震)和盗窃
1.2 分类
(1)从物理与逻辑的角度,备份可分为:
物理备份:对数据库操作系统的物理文件(如数据文件、日志文件等)的备份。
物理备份方法:
- 冷备份(脱机备份) :是在关闭数据库的时候进行的,依赖于数据文件。
- 热备份(联机备份) :数据库处于运行状态,依赖于数据库的日志文件。
- 温备份:数据库锁定表格(不可写入但可读)的状态下进行备份操作。
逻辑备份:对数据库逻辑组件(如: 表等数据库对象)的备份。
(2)按照数据库的备份策略角度,备份可分为:
- 完全备份:每次对数据进行完整的备份。
完全备份是对整个数据库的备份、数据库结构和文件结构的备份;完全备份保存的是备份完成时刻的数据库;完全备份也是增量备份的基础。
✔️优点:安全性高;备份与恢复操作简单方便
❌缺点:数据存在大量的重复;占用大量的备份空间,空间利用率低;备份与恢复时间长 - 差异备份:备份那些自从上次完全备份之后被修改过的文件。
- 增量备份:只有那些在上次完全备份或者增量备份后被修改的文件才会被备份。
增量备份就是备份自上一次备份之后增加或变化的文件或者内容,主要解决mysqldump命令完全备份存在的备份数据中有重复数据和备份时间与恢复时间长的问题。
✔️优点:没有重复数据,效率高,空间利用率最大化;备份量不大,时间短
❌缺点:恢复麻烦(需要上次完全备份及完全备份之后所有的增量备份才能恢复,而且要对所有增量备份进行逐个反推恢复);安全性较低
2 MySQL数据备份
2.1 mysqldump
mysqldump是MySQL自带的备份工具,可方便实现对MySQL的备份,可以将指定的库、表导出为SQL脚本。
(1)mysqldump命令
语法
mysqldump -h 服务器 -u用户名 -p密码 选项与参数 > 备份文件.sql
选项与参数 | 描述 |
---|---|
-A/--all-databases | 所有库 |
-B/--databases db1 db2 | 多个数据库 |
db1 | 数据库名 |
db1 t1 t2 | db1数据库的表t1、t2 |
-F | 备份的同时刷新binlog |
-d | 仅表结构 |
-t | 仅数据 |
--lock-all-tables | 备份过程中锁住所有表 |
--lock-tables | 如果是备份所有库,那么备份到某个库时只锁某个库,其他库可写 |
完整语句
mysqldump -uroot -p123123123 --databases db1 db2 > /backup/test.sql
(2)Shell脚本
可以通过shell脚本进行数据库连接、数据库备份及过期备份文件删除。👻
#!/bin/bash
# 配置信息
mysql_user="root" #MySQL备份用户
mysql_password="123123123" #MySQL备份用户的密码
mysql_host="192.168.0.1"
mysql_port="3306"
mysql_charset="utf8" #MySQL编码
backup_db_arr=("db1" "db2" "db3") #要备份的数据库名称,多个用空格分开隔开 如("db1" "db2" "db3")
backup_location=/data/mysql/backup #备份数据存放位置
expire_backup_delete="ON" #是否开启过期备份删除 ON为开启 OFF为关闭
expire_days=3 #过期时间天数 默认为三天,此项只有在expire_backup_delete开启时有效
backup_time=`date +%Y%m%d%H%M` #定义备份详细时间
backup_Ymd=`date +%Y-%m-%d` #定义备份目录中的年月日时间
backup_3ago=`date -d '3 days ago' +%Y-%m-%d` #3天之前的日期
backup_dir=$backup_location/$backup_Ymd #备份文件夹全路径
welcome_msg="Welcome to the MySQL backup tool!" #欢迎语
# 判断MYSQL是否启动,mysql没有启动则备份退出
mysql_ps=`ps -ef |grep mysql |wc -l`
mysql_listen=`netstat -an |grep LISTEN |grep $mysql_port|wc -l`
if [ [$mysql_ps == 0] -o [$mysql_listen == 0] ]; then
echo "ERROR: failed to start MySQL! Backup stopped!"
exit
else
echo $welcome_msg
fi
# 连接到mysql数据库,无法连接则备份退出
mysql -h$mysql_host -P$mysql_port -u$mysql_user -p$mysql_password <<end
use mysql;
select host,user from user where user='root' and host='localhost';
exit
end
flag=`echo $?`
if [ $flag != "0" ]; then
echo "ERROR: cannot connect MySQL server! Backup stopped!"
exit
else
echo "Connected to MySQL! Please wait......"
# 判断有没有定义备份的数据库,如果定义则开始备份,否则退出备份
if [ "$backup_db_arr" != "" ];then
#dbnames=$(cut -d ',' -f1-5 $backup_database)
#echo "arr is (${backup_db_arr[@]})"
for dbname in ${backup_db_arr[@]}
do
echo "database $dbname backup starts..."
`mkdir -p $backup_dir`
`mysqldump -h$mysql_host -P$mysql_port -u$mysql_user -p$mysql_password $dbname --default-character-set=$mysql_charset | gzip > $backup_dir/$dbname-$backup_time.sql.gz`
flag=`echo $?`
if [ $flag == "0" ];then
echo "database $dbname has been backed up to $backup_dir/$dbname-$backup_time.sql.gz succeessfully!"
else
echo "ERROR: failed to backup database $dbname!"
fi
done
else
echo "ERROR: No databases to be backed up! Backup stopped!"
exit
fi
# 如果开启了删除过期备份,则进行删除操作
if [ "$expire_backup_delete" == "ON" -a "$backup_location" != "" ];then
#`find $backup_location/ -type d -o -type f -ctime +$expire_days -exec rm -rf {} \;`
`find $backup_location/ -type d -mtime +$expire_days | xargs rm -rf`
echo "Expired backup data bas been deleted completely!"
fi
echo "All database backup has been done successfully!"
exit
fi
(3)使用XORM备份
可以使用XORM中的以下DumpAllToFile方法对MySQL数据库进行备份。
// DumpAllToFile dump database all table structs and data to a file
func (engine *Engine) DumpAllToFile(fp string, tp ...schemas.DBType) error {
f, err := os.Create(fp)
if err != nil {
return err
}
defer f.Close()
return engine.DumpAll(f, tp...)
}
可以使用beego.toolbox设置定时任务,定时备份数据库。
func RunBackupTask() {
toolbox.AddTask("backup", toolbox.NewTask("backup", "0 0 2 * * *", ExecBackup))
}
2.2 binlog
binlog是Mysql sever层维护的一种二进制日志,主要是用来记录对mysql数据更新或潜在发生更新的SQL语句,并以"事务"的形式保存在磁盘中。主要作用为:
- 复制:MySQL Replication在Master端开启binlog,Master把它的二进制日志传递给slaves并回放来达到master-slave数据一致的目的
- 数据恢复:通过mysqlbinlog工具恢复数据
- 增量备份
2.3 备份文件压缩
当数据库数据量很大时,.sql文件可能会很大。所以在dump备份完成后,可以对.sql文件进行压缩。
2.4 远程同步到备份服务器
在某些场景下,可能需要将备份文件同步存储到备份服务器上,以避免服务器出现故障时,连同备份文件一起丢失的情况。
Linux中可以用来远程同步、远程备份数据的命令是rsync。rsync 可以理解为 remote sync(远程同步)。
要使用rsync进行远程数据备份,需要在本地和远端都安装rsync。
使用 rsync 命令备份数据时,不会直接覆盖以前的数据(如果数据已经存在),而是先判断已经存在的数据和新数据的差异,只有数据不同时才会把不相同的部分覆盖。
rsync 命令的基本格式有多种,分别是:
[root@localhost ~]# rsync [OPTION] SRC DEST
[root@localhost ~]# rsync [OPTION] SRC [USER@]HOST:DEST
[root@localhost ~]# rsync [OPTION] [USER@]HOST:SRC DEST
[root@localhost ~]# rsync [OPTION] [USER@]HOST::SRC DEST
[root@localhost ~]# rsync [OPTION] SRC [USER@]HOST::DEST
各个参数的含义如下:
- SRC:用来表示要备份的目标数据所在的位置(路径);
- DEST:用于表示将数据备份到什么位置;
- USER@:当做远程同步操作时,需指明系统登录的用户名,如果不显示指定,默认为以 root 身份登录系统并完成同步操作。
针对以上 5 种命令格式,rsync 有 5 种不同的工作模式:
- 第一种用于仅在本地备份数据;
- 第二种用于将本地数据备份到远程机器上;
- 第三种用于将远程机器上的数据备份到本地机器上;
- 第四种和第三种是相对的,同样第五种和第二种是相对的,它们各自之间的区别在于登陆认证时使用的验证方式不同。
Note:在使用 rsync 在远程传输数据(备份数据)前,是需要进行登陆认证的,这个过程需要借助 ssh 协议或者 rsync 协议才能完成。在 rsync 命令中,如果使用单个冒号(:),则默认使用 ssh 协议;反之,如果使用两个冒号(::),则使用 rsync 协议。
ssh 协议和 rsync 协议的区别在于,rsync 协议在使用时需要额外配置,增加了工作量,但优势是更加安全;反之,ssh 协议使用方便,无需进行配置,但有泄漏服务器密码的风险。
Rsync OPTION选项:
OPTION选项 | 描述 |
---|---|
-a | 这是归档模式,表示以递归方式传输文件,并保持所有属性,它等同于-r、-l、-p、-t、-g、-o、-D 选项。-a 选项后面可以跟一个 --no-OPTION,表示关闭 -r、-l、-p、-t、-g、-o、-D 中的某一个,比如-a --no-l 等同于 -r、-p、-t、-g、-o、-D 选项。 |
-r | 表示以递归模式处理子目录,它主要是针对目录来说的,如果单独传一个文件不需要加 -r 选项,但是传输目录时必须加。 |
-v | 表示打印一些信息,比如文件列表、文件数量等。 |
-l | 表示保留软连接。 |
-p | 表示保持文件权限。 |
-o | 表示保持文件属主信息。 |
-g | 表示保持文件属组信息。 |
-D | 表示保持设备文件信息。 |
-t | 表示保持文件时间信息。 |
--delete | 表示删除 DEST 中 SRC 没有的文件。 |
--exclude=PATTERN | 表示指定排除不需要传输的文件,等号后面跟文件名,可以是通配符模式(如 *.txt)。 |
--progress | 表示在同步的过程中可以看到同步的过程状态,比如统计要同步的文件数量、 同步的文件传输速度等。 |
-u | 表示把 DEST 中比 SRC 还新的文件排除掉,不会覆盖。 |
-z | 加上该选项,将会在传输过程中压缩。 |
在golang中的实现:
(1)调用命令
func Rsync(host, port, user, password, target, src string) error {
command := fmt.Sprintf("sshpass -p %v rsync -avz --port=%v %v %v@%v::%v", password, port, src, user, host, target)
cmd := exec.Command("sh", "-c", command)
output, err := cmd.Output()
if err != nil {
fmt.Println("failed to execute Rsync Shell:", command, " with error: ", err.Error())
return err
}
fmt.Println("execute Rsync Shell:", command, " successfully with output:\n", string(output))
return nil
}
(2)调用shell脚本
shell脚本如下,文件名为rsync.sh,存放在main函数同级的目录中。
#!/bin/sh
sshpass -p$1 rsync -avz --port=$2 $3 $4@$5::$6
func Rsync(host, port, user, password, target, src string) error{
command:=fmt.Sprintf("./rsync.sh %v %v %v %v %v %v",password,port, src, user, host, target)
cmd := exec.Command("sh", "-c", command)
output, err := cmd.Output()
if err != nil {
fmt.Println("failed to execute Rsync Shell:", command, " with error: ", err.Error())
return err
}
fmt.Println("execute Rsync Shell:", command, " successfully with output:\n", string(output))
return nil
}
通过以上两种方式都可以进行rsync远程备份。
3 数据库恢复
3.1 利用数据库工具(Navicat)
选择相应的数据库进行运行SQL文件,恢复相应数据库中的结构与数据。
3.2 mysql命令
mysql -u 用户名 -p密码 要恢复的数据库名称 < 库备份脚本的路径/备份文件
例:
mysql -u root -p123123123 db1 < /usr/local/db1.sql
3.3 source命令
执行步骤
step 1 将备份文件拷贝至容器中
docker cp 主机中备份脚本的位置 containerID:容器中要放备份文件的位置
例:docker cp /data/db1.sql b1e067acbbe3:/usr/local/db1.sql
step 2 进入相应的容器中
docker exec -it mysql /bin/bash
step 3 登录mysql
mysql -u用户名 -p密码
step 4 source
use db1;
source /usr/local/db1.sql
如果db1数据库不存在,需要先create database db1;然后use db1;再进行source。
Reference List:
https://blog.csdn.net/qq_46480020/article/details/111603417
https://blog.csdn.net/SHISHIZHIZHI/article/details/121081817
binlog https://zhuanlan.zhihu.com/p/33504555
zip code https://gitee.com/countpoison/youbei
rsync http://c.biancheng.net/view/6121.html