Perl写的简单的MySQL备份脚本
2013-04-17 20:39:10 阿炯

本站赞助商链接,请多关照。 介绍一个Perl写的MySQL数据库备份脚本,放在crontab中让其自动运行,它在运行会调用'mysqldump'进行备份,只需要对脚本进行简单的修改即可。脚本具备日志功能,一库一文件,并在当次的备份文件放在以日期命名的目录下。因为库与库之间有关联,所有在备份时一定要所有库都不能有写,以保证完好的一致性;更多关于备份时锁表的问题,可参考文章:对mysqldump在备份数据库时锁表的认识

#!/usr/bin/perl
use POSIX qw(strftime);
use File::Path 'rmtree';
use Data::Dumper;
use DBI;
use DBD::mysql;
use Log::Handler;
use IO::Compress::Gzip qw(gzip $GzipError);

#20101023
#数据库备份脚本
#将每一个库备份成为一个文件
#1.到mysql数据库服所在的data目录取得相关库目录,只要目录
#2.依次对这些库目录调用mysqldump成为文件
#20130328
#按以日期命名的目录存放当次的备份文件
#从开始加锁至本次备份完成
#20130416
#在dump期间不使用gzip工具来压缩,以减少锁表的时间,在导出完成
#后在对其进行压缩处理.加入了运行日志记录功能.加入了数据库
#排除备份的功能
###################
#mysql数据库服务器数据(data)目录
my $mydatadir='/data/mysql/var3306';
#存放备份数据文件的目录,不必在尾部加'/'
my $bakdir='/home/backup';
#到数据库的连接信息
my $dbhost='127.0.0.1';
my $dbuser='dba';
my $dbpasswd='dbpasswd';
my $dbsock='/tmp/mysqld3306.sock';
#历史备份数据存放时间,这里数据将保存30天
my $histroy=30;
#排除要备份的库
my @exdb=('test','tmpuse');
###################

#取得当前日期
my $dt=strftime "%Y%m%d",localtime $^T;


#创建对应的目录
unless (-e "$bakdir/$dt"){
  die "create dir $_ has failed!" unless mkdir("$bakdir/$dt");
}


my $log = Log::Handler->new();
$log->add(
file => {
 # handler options (see Log::Handler)
 timeformat => "%Y-%m-%d %H:%M:%S",
 message_layout => "%T [%L] %s:%m",
 maxlevel => "info",
 minlevel => "emergency",
 die_on_errors => 1,
 # file options (see Log::Handler::Output::File)
 filename => "$bakdir/$dt/run.log",
 filelock => 1,
 fileopen => 1,
 reopen => 1,
 autoflush => 1,
 permissions => "0660",
 utf8 => 1,}
);

#取得需要处理的数据库
sub get_db_list{
 my $ldir=shift @_;
 if(opendir(DIR, $ldir)){
 my @dots = grep {/[^\.]/ && -d "$ldir/$_"} readdir(DIR);
 #@dots = map { "$ldir/$_/" } @dots;
 closedir DIR;
 $log->info("get dir $ldir structure succeed.");
 return @dots;
 }else{
  $log->emerg("get dir $ldir structure filed.");
  die "Get $ldir failed";
 }
}

#取得要备份的数据库名
my @dbs=get_db_list($mydatadir);

#开始建立连接到数据库并锁表
$dbh=DBI->connect("DBI:mysql:database=mysql;mysql_socket=$dbsock;user=$dbuser;password=$dbpasswd");
if($dbh->do('FLUSH TABLES WITH READ LOCK')){
 $log->info("db add lock succeed.");
}else{
 $log->error("db add lock failed.");
 warn $dbh->errstr;
}

#备份程序
sub dumper{
 my $db=shift @_;
 my $sqldump="/usr/local/mysql/bin/mysqldump --host=$dbhost --user=$dbuser --password=$dbpasswd --databases $db --add-drop-table --add-locks --complet
e-insert --routines --hex-blob --triggers >$bakdir/$dt/$db.sql";
 if(qx/$sqldump/ == 0){
  $log->info("db $db backup has done.");
 }else{
  $log->error("db $db backup failed.");
  warn "system $sqldump failed: $?"
 }

}


#开始备份
for my $db (@dbs){
 #在此还可以排除一些不想备份的库
 next if (grep /$db/,@exdb);
 $log->info("prepare backup db $db.");
 dumper($db);
}

#释放掉表锁
$dbh->do('unlock tables;');
$log->info("db unlock succeed");

#对备份好的文件进行压缩
sub gzipfile{
for my $file (glob "$bakdir/$dt/*.sql"){
 $log->info("gzip file:$file");
 my $output = "$file.gz" ;
 gzip $file=>$output or die "Error compressing '$file': $GzipError\n";
 if(unlink $file){
  $log->info("file $file has deleted.");
 }else{
  $log->error("file $file delete failed.");
 }
}

}

gzipfile;

#清除历史备份数据
sub del_histroy_file{
 my $dtdir=strftime "%Y%m%d",(localtime $^T - 24*60*60*$histroy);
 my $rmdir="$bakdir/$dtdir";
 $log->info("delete dir $rmdir");
 rmtree($rmdir,{verbose=>1}) if (-e $rmdir);
}

del_histroy_file;