Mydumper是一个针对MySQL和Drizzle的高性能多线程备份和恢复工具。开发人员主要来自MySQL,Facebook,SkySQL公司。目前已经在一些线上使用了Mydumper。虽然MySQL数据库备份工具有其自带的mysqldump,属于mysql官方的一款备份工具。但是第三方备份工具mydumper凭借优越的特点为更多人所使用。
1、Mydumper安装
# yum install glib2-devel mysql-devel zlib-devel pcre-devel
# wget http://launchpad.net/mydumper/0.5/0.5.1/+download/mydumper-0.5.1.tar.gz
# tar zxvf mydumper-0.5.1.tar.gz -C ../software/
# cmake .
# make
# make install
2、在mysql数据库中创建一个测试库和表(进入mysql数据库)
create database test;
create table test (a int);
mydumper参数介绍:
-B, --database 需要备份的库
-T, --tables-list 需要备份的表,用,分隔
-o, --outputdir 输出目录
-s, --statement-size Attempted size of INSERT statement in bytes, default 1000000
-r, --rows 试图分裂成很多行块表
-c, --compress 压缩输出文件
-e, --build-empty-files 即使表没有数据,还是产生一个空文件
-x, --regex 支持正则表达式
-i, --ignore-engines 忽略的存储引擎,用,分隔
-m, --no-schemas 不导出表结构
-k, --no-locks 不执行临时共享读锁 警告:这将导致不一致的备份
-l, --long-query-guard 长查询,默认60s
--kill-long-queries kill掉长时间执行的查询(instead of aborting)
-b, --binlogs 导出binlog
-D, --daemon 启用守护进程模式
-I, --snapshot-interval dump快照间隔时间,默认60s,需要在daemon模式下
-L, --logfile 日志文件
-h, --host
-u, --user
-p, --password
-P, --port
-S, --socket
-t, --threads 使用的线程数,默认4
-C, --compress-protocol 在mysql连接上使用压缩
-V, --version
-v, --verbose 更多输出, 0 = silent, 1 = errors, 2 = warnings, 3 = info, default 2
myloader参数介绍:
-d, --directory 导入备份目录
-q, --queries-per-transaction 每次执行的查询数量, 默认1000
-o, --overwrite-tables 如果表存在删除表
-B, --database 需要还原的库
-e, --enable-binlog 启用二进制恢复数据
-h, --host
-u, --user
-p, --password
-P, --port
-S, --socket
-t, --threads 使用的线程数量,默认4
-C, --compress-protocol 连接上使用压缩
-V, --version
-v, --verbose 更多输出, 0 = silent, 1 = errors, 2 = warnings, 3 = info, default 2
mydumper输出文件:
metadata:元数据 记录备份开始和结束时间,以及binlog日志文件位置。
table data:每个表一个文件
table schemas:表结构文件
binary logs: 启用--binlogs选项后,二进制文件存放在binlog_snapshot目录下
daemon mode:在这个模式下,有五个目录0,1,binlogs,binlog_snapshot,last_dump。
备份目录是0和1,间隔备份,如果mydumper因某种原因失败而仍然有一个好的快照,
当快照完成后,last_dump指向该备份。
time mydumper -B test -o /tmp/test2.bak -r 5000
mydumper备份脚本
#!/bin/bash
#ocpyang@126.com
########脚本说明
#1.默认读取当前目录下database.txt文件,备份部分数据库
#2.如果database.txt为空,则执行全备或备份指定的个别数据库
#set parameter
mydumper=/usr/local/bin/mydumper #根据自己的实际情况设置
dir_backup=/backup #根据自己的实际情况设置
mysql_host=localhost #根据自己的实际情况设置
mysql_port=33306 #根据自己的实际情况设置
mysql_user=root #根据自己的实际情况设置
mysql_pass=123456 #根据自己的实际情况设置
now_date=`date +%Y%m%d%H%M`
if [ ! -d $dir_backup ]; then
echo -e "\e[1;31m 保存备份的主目录:$dir_backup不存在,将自动新建. \e[0m"
mkdir -p ${dir_backup}
fi
export black='\033[0m'
export boldblack='\033[1;0m'
export red='\033[31m'
export boldred='\033[1;31m'
export green='\033[32m'
export boldgreen='\033[1;32m'
export yellow='\033[33m'
export boldyellow='\033[1;33m'
export blue='\033[34m'
export boldblue='\033[1;34m'
export magenta='\033[35m'
export boldmagenta='\033[1;35m'
export cyan='\033[36m'
export boldcyan='\033[1;36m'
export white='\033[37m'
export boldwhite='\033[1;37m'
cecho ()
## -- Function to easliy print colored text -- ##
# Color-echo.
# 参数 $1 = message
# 参数 $2 = color
{
local default_msg="No message passed."
message=${1:-$default_msg} # 如果$1没有输入则为默认值default_msg.
color=${2:-black} # 如果$1没有输入则为默认值black.
case $color in
black)
printf "$black" ;;
boldblack)
printf "$boldblack" ;;
red)
printf "$red" ;;
boldred)
printf "$boldred" ;;
green)
printf "$green" ;;
boldgreen)
printf "$boldgreen" ;;
yellow)
printf "$yellow" ;;
boldyellow)
printf "$boldyellow" ;;
blue)
printf "$blue" ;;
boldblue)
printf "$boldblue" ;;
magenta)
printf "$magenta" ;;
boldmagenta)
printf "$boldmagenta" ;;
cyan)
printf "$cyan" ;;
boldcyan)
printf "$boldcyan" ;;
white)
printf "$white" ;;
boldwhite)
printf "$boldwhite" ;;
esac
printf "%s\n" "$message"
tput sgr0# tput sgr0即恢复默认值
printf "$black"
return
}
cechon ()
# Color-echo.
# 参数1 $1 = message
# 参数2 $2 = color
{
local default_msg="No message passed."
# Doesn't really need to be a local variable.
message=${1:-$default_msg} # 如果$1没有输入则为默认值default_msg.
color=${2:-black} # 如果$1没有输入则为默认值black.
case $color in
black)
printf "$black" ;;
boldblack)
printf "$boldblack" ;;
red)
printf "$red" ;;
boldred)
printf "$boldred" ;;
green)
printf "$green" ;;
boldgreen)
printf "$boldgreen" ;;
yellow)
printf "$yellow" ;;
boldyellow)
printf "$boldyellow" ;;
blue)
printf "$blue" ;;
boldblue)
printf "$boldblue" ;;
magenta)
printf "$magenta" ;;
boldmagenta)
printf "$boldmagenta" ;;
cyan)
printf "$cyan" ;;
boldcyan)
printf "$boldcyan" ;;
white)
printf "$white" ;;
boldwhite)
printf "$boldwhite" ;;
esac
printf "%s" "$message"
tput sgr0# tput sgr0即恢复默认值
printf "$black"
return
}
judegedate_01="judegedate01.`date +%y%m%d%h%m%s`.txt"
schema_judege01="select schema_name from information_schema.schemata ;"
mysql -h${mysql_host} -P${mysql_port} -u${mysql_user} -p${mysql_pass} -e"${schema_judege01}" >${judegedate_01}
echo -e "\e[1;31m The databases name in current instance is: \e[0m"
awk 'NR==2,NR==0 { print $1}' ${judegedate_01}
echo " "
#Get the current script path and create a file named database.txt
#in order to save the backup databases name.
filepath=$(cd "$(dirname "$0")"; pwd)
if [ ! -s "${filepath}/database.txt" ];then
echo "将在当前目录下新建databases.txt."
touch ${filepath}/database.txt
echo "#Each line is stored a valid database name">${filepath}/database.txt
chmod 700 ${filepath}/database.txt
fi
#Remove the comment line
awk 'NR==2,NR==0 { print $1}' ${filepath}/database.txt> ${filepath}/tmpdatabases.txt
#To determine whether a file is empty
if [ -s ${filepath}/tmpdatabases.txt ];then
#开始时间
started_time=`date +%s`
echo "备份开始时间:${started_time}"
db_num00=`awk 'NR==1,NR==0 { print NR}' ${filepath}/tmpdatabases.txt |tail -n1`
echo "此次将备份${db_num00}个数据库:"
echo
or_dbnum=0
for i in `awk 'NR==1,NR==0 { print $1}' ${filepath}/tmpdatabases.txt`;
do
((or_dbnum+=1))
mysql_databases=$i
db_dpname=$dir_backup/${i}.${now_date}
echo -e "\e[1;32m mydumper开始备份第${or_dbnum}个数据库$i..... \e[0m"
sleep 2
echo -e "\e[1;32m mydumper玩命备份中.....稍等片刻.... \e[0m"
${mydumper} \
--database=${mysql_databases} \
--host=${mysql_host} \
--port=${mysql_port} \
--user=${mysql_user} \
--password=${mysql_pass} \
--outputdir=${db_dpname} \
--no-schemas \
--rows=50000 \
--build-empty-files \
--threads=4 \
--compress-protocol \
--kill-long-queries
if [ "$?" -eq 0 ];then
echo -e "\e[1;32m mydumper成功将数据库$i备份到:${db_dpname}. \e[0m"
echo
else
echo -e "\e[1;31m 备份异常结束. \e[0m"
fi
done
else
ipname=''
read -p "Please input you want to backup database name[a|A:ALL]:" ipname
#开始循环
#开始时间
started_time=`date +%s`
echo "备份开始时间:${started_time}"
if [ "$ipname" = "a" -o "$ipname" = "A" ];then
db_num=`awk 'NR==2,NR==0 { print NR-1}' ${judegedate_01} |tail -n1`
echo "此次将备份${db_num}个数据库:"
echo
mysql_databases=$ipname
or_dbnum=0
for i in `awk 'NR==2,NR==0 { print $1}' ${judegedate_01}`;
do
((or_dbnum+=1))
mysql_databases=$i
db_dpname=$dir_backup/${i}.${now_date}
echo -e "\e[1;32m mydumper开始备份第${or_dbnum}个数据库$i..... \e[0m"
sleep 2
echo -e "\e[1;32m mydumper玩命备份中.....稍等片刻.... \e[0m"
${mydumper} \
--database=${mysql_databases} \
--host=${mysql_host} \
--port=${mysql_port} \
--user=${mysql_user} \
--password=${mysql_pass} \
--outputdir=${db_dpname} \
--no-schemas \
--rows=50000 \
--build-empty-files \
--threads=4 \
--compress-protocol \
--kill-long-queries
if [ "$?" -eq 0 ];then
echo -e "\e[1;32m mydumper成功将数据库$i备份到:${db_dpname}. \e[0m"
echo
else
echo -e "\e[1;31m 备份异常结束. \e[0m"
fi
done
else
echo "此次备份的数据库名为:$ipname"
echo
#开始时间
STARTED_TIME=`date +%s`
mysql_databases=$ipname
db_dpname=$dir_backup/${mysql_databases}.${now_date}
judegedate_02="judegedate02.`date +%y%m%d%h%m%s`.txt"
schema_judege02="select schema_name from information_schema.schemata where schema_name='${ipname}';"
mysql -h${mysql_host} -P${mysql_port} -u${mysql_user} -p${mysql_pass} -e"${schema_judege02}" >${judegedate_02}
if [ ! -s "${judegedate_02}" ];then
echo ""
echo -e "\e[1;31m ******************************************************************* \e[0m"
echo -e "\e[1;31m !o(︶︿︶)o! The schema_name ${ipname} not exits,pleae check . ~~~~(>_<)~~~~ \e[0m"
echo -e "\e[1;31m ********************************************************************** \e[0m"
echo ""
rm -rf ${judegedate_01}
rm -rf ${judegedate_02}
exit 0
else
echo -e "\e[1;32m mydumper开始备份请稍等..... \e[0m"
sleep 2
echo -e "\e[1;32m mydumper玩命备份中.....稍等片刻.... \e[0m"
${mydumper} \
--database=${mysql_databases} \
--host=${mysql_host} \
--port=${mysql_port} \
--user=${mysql_user} \
--password=${mysql_pass} \
--outputdir=${db_dpname} \
--no-schemas \
--rows=50000 \
--build-empty-files \
--threads=4 \
--compress-protocol \
--kill-long-queries
if [ "$?" -eq 0 ];then
echo -e "\e[1;32m mydumper成功将数据库备份到:${db_dpname}. \e[0m"
else
echo -e "\e[1;31m 备份异常结束. \e[0m"
fi
fi
# 循环结束
fi
fi
rm -rf ${judegedate_01}
rm -rf ${judegedate_02}
rm -rf ${filepath}/tmpdatabases.txt
echo "完成于: `date +%F' '%T' '%w`"
######################################################################################################################
执行结果如下:#####################
The databases name in current instance is:
information_schema
mysql
performance_schema
test
wind
mpiao
mpadmin
mplog
Please input you want to backup database name[a|A:ALL]:A
备份开始时间:1431574874
此次将备份8个数据库:
mydumper开始备份第1个数据库information_schema.....
mydumper玩命备份中.....稍等片刻....
mydumper成功将数据库information_schema备份到:/backup/information_schema.201505141141.
mydumper开始备份第2个数据库mysql.....
mydumper玩命备份中.....稍等片刻....
mydumper成功将数据库mysql备份到:/backup/mysql.201505141141.
mydumper开始备份第3个数据库performance_schema.....
mydumper玩命备份中.....稍等片刻....
mydumper成功将数据库performance_schema备份到:/backup/performance_schema.201505141141.
mydumper开始备份第4个数据库test.....
mydumper玩命备份中.....稍等片刻....
mydumper成功将数据库test备份到:/backup/test.201505141141.
mydumper开始备份第5个数据库wind.....
mydumper玩命备份中.....稍等片刻....
mydumper成功将数据库wind备份到:/backup/wind.201505141141.
mydumper开始备份第6个数据库mpiao.....
mydumper玩命备份中.....稍等片刻....
mydumper成功将数据库mpiao备份到:/backup/mpiao.201505141141.
mydumper开始备份第7个数据库mpadmin.....
mydumper玩命备份中.....稍等片刻....
mydumper成功将数据库mpadmin备份到:/backup/mpadmin.201505141141.
mydumper开始备份第8个数据库mplog.....
mydumper玩命备份中.....稍等片刻....
mydumper成功将数据库mplog备份到:/backup/mplog.201505141141.
Mydumper备份脚本模板
# 这是一个本地备份多台MYSQL的脚本
# 设定被备份主机信息
TYPE=ALL
IPADDR=localhost
PASSWD=密码
# 指定主目录
BACKUP_FILES_PATH="/home/ftp/b/backup_data/mydumper"
# 以当前系统时间新建备份文件夹
TIME_DIR=$(date -d "yesterday" +"%Y")/$(date +"%m")/$(date +"%d")/$(date +"%Y%m%d%H%M%S")
BACKUP_FILES_DIR=${BACKUP_FILES_PATH}/$TYPE/$TIME_DIR;echo "新建备份目录:$BACKUP_FILES_DIR"
# 设置你想保存的天数,我这里设置的是保存30天之内的备份
SAVE_DAYS=30
# 删除指定时间前的文件
find $BACKUP_FILES_PATH -mtime +$SAVE_DAYS -exec rm -rf {} \;
# 新建备份目录
echo "新建备份目录:$BACKUP_FILES_DIR"
mkdir -p $BACKUP_FILES_DIR
echo "备份对象:$IPADDR">$BACKUP_FILES_DIR/log
# 开始远程备份
# mydumper只需要3个全局权限 SELECT, RELOAD, LOCK TABLES
# 如果记录需要二进制日志和指针信息 需要再添加2个权限 REPLICATION SLAVE, REPLICATION CLIENT
time mydumper -h $IPADDR -u mydumper -p $PASSWD -o $BACKUP_FILES_DIR -c 9 -C -e -t 6 2>>$BACKUP_FILES_DIR/log
cat $BACKUP_FILES_DIR/metadata
cat $BACKUP_FILES_DIR/log
# 复制最新的到外层文件夹
rm -rf ${BACKUP_FILES_PATH}/$TYPE/LastBackUp
cp -r $BACKUP_FILES_DIR ${BACKUP_FILES_PATH}/$TYPE/LastBackUp
# 设定权限
chown -R 1018:1100 $BACKUP_FILES_DIR
# 恢复
# time myloader -h localhost -u root -p 密码 -d /home/ftp/b/backup_data/mydumper/ALL/LastBackUp -o -v 3 -C -t 6
# 追加此脚本到计划任务
# echo "17 05 * * * sh /root/shell/backup_mysql.sh" >> /var/spool/cron/root
# echo "06 05 * * * sh /root/shell/backup_mysql.sh" >> /var/spool/cron/root