也许你会有疑问,shell这么简单的脚本语言有多线程一说吗?答案是有的,只不过它实现起来有些难理解罢了,因为它借助了命名管道实现。所谓多线程就是将原来由一个进程完成的事情现在由多个线程去完成。假如一个进程需要10个小时完成的事情,现在分配给10个线程,给它们分工,然后同时去做这件事情,最终可能就需要1个小时。
本案例就是实现shell多线程备份数据库,具体要求如下:
1)公司的业务量比较大,有100个数据库需要全量备份,而每个数据库的数据量高达几十GB
(注意:每一个库都为一个独立的实例,即有着独立的ip:port);
2)预估每一个库的备份时间为30分钟左右,要求在5个小时内完成;
3)假设100个库的库名、host、port以及配置文件路径都存到一个文件里,文件名字为 /tmp/databases.list ;
4)格式为:db1 10.10.10.2 3308 /data/mysql/db1/my.cnf 。
要想在5小时内完成100个数据库的备份,需要使用shell脚本的多线程功能,一次性开10个线程同时并发备份10个数据库。
参考脚本如下:
#!/bin/bash
#多线程备份数据库
#备份数据库使用xtrabackup(由于涉及到myisam,命令为innobackupex)
exec &> /tmp/mysql_bak.log
if ! which inoobackupex &>/dev/null
then
echo "安装xtrabackup工具"
yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
yum install percona-xtrabackup-24
if [ $? -ne 0 ]
then
echo -e "\033[31m安装xtrabackup工具出错,请检查\033[0m"
exit 1
fi
fi
bakdir=/data/backup/mysql
bakuser=vyNctM
bakpass=99omeaBHh
bak_data()
{
db_name=$1
db_host=$2
db_port=$3
cnf=$4
[ -d $bakdir/$db_name ] || mkdir -p $bakdir/$db_name
innobackupex --defaults-file=$4 --host=$2 --port=$3 --user=$bakuser --password=$bakpass --databases=$1 $bakdir
if [ $? -ne 0 ]
then
echo -e "\033[31m备份数据库$1出现问题\033[0m"
fi
}
fifofile=/tmp/$$
mkfifo $fifofile
exec 1000<>$fifofile
n=10
for ((i=0;i<$n;i++))
do
echo >&1000 # 0-9,创建10个线程
done
cat /tmp/databases.list |while read line
do
read -u1000
{
bak_data `echo $line`
echo >&1000
} &
done
wait
exec 1000>&- #删除fd1000
rm -f $fifofile #删除命名管道
脚本中,
-
exec &> /tmp/mysql_bak.log ,将正确输出和错误输出都重定向到 /tmp/mysql_bak.log
-
$$表示本进程PID,mkfifo命令创建命名管道
-
read line ,line为变量名,将接下来的输入赋值给line