前几天网站数据库因为一个误操作导致数据全部丢失,更加悲剧的是由于疏忽只有几个月前的备份,而最近几个月网站内容增加了很多(出来混迟早是要还的啊!!!),万幸的是在配置服务器的时候打开了二进制日志。于是用了一天一夜从几十G的日志文件中恢复了数据。亡羊补牢,赶紧配置上了完全备份和增量备份。备份策略是:每周进行一次完全备份,每天一次增量备份。完全备份采用的是mysqldump,增量备份是基于二进制日志的。配置自动备份的过程中查了不少资料,感觉网上的都是重复的资料,解释也不是很清楚,下面把查到的资料和自己的一些理解记录下来,方便自己做个记录也给需要的提供点方便。
数据库:mysql 5.1.54
数据库引擎:MyISAM(下面的备份仅适用于MyISAM,而且已经在线上服务器运行有效,InnoDB有一点修改,请自行查找并测试)
操作系统:ubuntu10.04
完全备份:
完全备份采用的命令:mysqladmin -u XXX -pXXX flush-tables
mysqldump -u XXX -pXXX --master-data=2 --flush-logs --delete-master-logs --databases db1 db2 > backup.sql
其中需要注意的是-p后面紧接着的是密码(中间没有空格),这样就不用手动输入密码了。第一行是为备份做准备,目的是mysql执行flush-tables命令,将缓存中的数据写入到文件中。第二行是主要的备份命令。 --master-data=2的意思是在生成的备份文件开头加入此次备份截至到二进制日志的编号,为以后的增量备份做准备。此外需要注意的是使用--master-data[=#]参数时默认使用了参数--lock-all-tables on。而--lock-all-tables on参数的意思是通过试用一个全局读锁锁定整个mysql数据库,同时这个参数mysqldump的第二个参数--flush-logs也有影响。--flush-logs是新建二进制日志。在同时备份多个数据库时如果有多个数据库(如例子中的db1 db2)则新建多个二进制日志(新建日志数目与数据库个数相同),但是如果有参数--lock-all-tables on,则无论多少个数据库只新建一个二进制日志。--delete-master-logs删除除了新生成的二进制日志外所有的日志文件。因为随着网站运行日志文件会越来越大,需要删除以释放空间。至于-u,-p,-databases命令就不用解释了。
我写的数据库完整备份shell脚本#!/bin/sh
#使用mysqldump备份数据库
#备份时间暂定为每周一次,写在crontab中
today=`date +"%Y_%m_%d_%H_%M_%S"`
#backupTimes是备份保留份数。
backupTimes=4
delete()
{
i=0
for fullBackFill in `ls -t full*`
do
i=$((i+1))
if [ $backupTimes -lt $i ]
then
rm $fullBackFill
fi
done
}
backupbasedir=/home/ftp/backup/full/
cd $backupbasedir
today_bkdir=$backupbasedir"full"$today".sql"
mysqladmin -u XXX -pXXX flush-tables
#mysqldump参数:--master-data=2是为了在mysqldump导出的文件开头写上pos,供恢复用。另外该参数默认执行--lock-all-tables
#这次备份会删除以前的二进制日志
mysqldump -u XXX -pXXX --master-data=2 --flush-logs --delete-master-logs --databases db1 db2 > $today_bkdir
#删掉早于4次(这个数由backupTimes决定)的备份
delete
增量备份:
增量备份使用的命令mysqladmin -u XXX -pXXX flush-tables
mysqladmin -u XXX -pXXX flush-logs
命令作用已经在上面讲过,不再赘述。
增量备份shell脚本#!/bin/sh
mysqladmin -u XXX -pXXX flush-tables
mysqladmin -u XXX -pXXX flush-logs
backupDir=/home/ftp/backup/incremental/
time=`date +%Y_%m_%d_%H_%M_%S`
timeFolder=$backupDir$time"/"
echo $timeFolder
if [ -e $timeFolder ]
then
echo
else
mkdir -p $timeFolder
fi
i=0
for binfile in `ls -t /usr/local/mysql/var/mysql-bin.[0-9]*`
do
i=$((i + 1))
if [ 1 -eq $i ]
then
echo "The new generated bin-log: "$binfile
else
filename=$(basename $binfile)
# echo $binfile
mv $binfile $timeFolder$filename
fi
done
需要注意的是备份脚本由于环境变量,权限配置等等原因只适用于本服务器,贴出来是让给大家一个参考,也希望反馈些建议。请参考脚本结合各自环境使用。