Perl写的简单的MySQL备份脚本
介绍一个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;