# Handle for options
if ($opt{'f'}){
$srcfile = $opt{'f'};
}else{
&merror("please input binlog file");
}
$opt{'h'} and $host = $opt{'h'};
$opt{'u'} and $user = $opt{'u'};
$opt{'p'} and $pwd = $opt{'p'};
$opt{'P'} and $port = $opt{'P'};
if ($opt{'o'}) {
$outfile = $opt{'o'};
# 清空 outfile
`echo '' > $outfile`;
}
#
$MYSQL = qq{mysql -h$host -u$user -p'$pwd' -P$port};
&mdebug("get_options::MYSQL\n\t$MYSQL");
# 提取binlog,不需要显示列定义信息,用-v,而不用-vv
$MYSQLBINLOG = qq{mysqlbinlog -v};
$MYSQLBINLOG .= " --start-position=".$opt{'start-position'} if $opt{'start-position'};
$MYSQLBINLOG .= " --stop-position=".$opt{'stop-position'} if $opt{'stop-postion'};
$MYSQLBINLOG .= " --start-datetime='".$opt{'start-datetime'}."'" if $opt{'start-datetime'};
$MYSQLBINLOG .= " --stop-datetime='$opt{'stop-datetime'}'" if $opt{'stop-datetime'};
$MYSQLBINLOG .= " $srcfile";
&mdebug("get_options::MYSQLBINLOG\n\t$MYSQLBINLOG");
# 检查binlog中是否含有 ddl sql: CREATE|ALTER|DROP|RENAME
&check_binlog() unless ($opt{'i'});
# 不使用mysqlbinlog过滤,USE dbname;方式可能会漏掉某些sql,所以不在mysqlbinlog过滤
# 指定数据库
if ($opt{'d'}){
my @dbs = split(/,/,$opt{'d'});
foreach my $db (@dbs){
$do_dbs{$db}=1;
}
}
# 指定表
if ($opt{'T'}){
my @tbs = split(/,/,$opt{'T'});
foreach my $tb (@tbs){
$do_tbs{$tb}=1;
}
}
# 提取有效DML SQL
$ROLLBACK_DML = $MYSQLBINLOG." | grep '^### '";
# 去掉注释: '### ' -> ''
# 删除首尾空格
$ROLLBACK_DML .= " | sed 's/###\\s*//g;s/\\s*\$//g'";
&mdebug("rollback dml\n\t$ROLLBACK_DML");
# 检查内容是否为空
my $cmd = "$ROLLBACK_DML | wc -l";
&mdebug("check contain dml sql\n\t$cmd");
my $size = `$cmd`;
chomp($size);
unless ($size >0){
&merror("binlog DML is empty:$ROLLBACK_DML");
};
}
# ----------------------------------------------------------------------------------------
# Func : check binlog contain DDL
# ----------------------------------------------------------------------------------------
sub check_binlog{
&mdebug("$PRE_FUNCT check_binlog");
my $cmd = "$MYSQLBINLOG ";
$cmd .= " | grep -E -i '^(CREATE|ALTER|DROP|RENAME)' ";
&mdebug("check binlog has DDL cmd\n\t$cmd");
my $ddlcnt = `$cmd`;
chomp($ddlcnt);
my $ddlnum = `$cmd | wc -l`;
chomp($ddlnum);
my $res = 0;
if ($ddlnum>0){
# 在ddl sql前面加上前缀<DDL>
$ddlcnt = `echo '$ddlcnt' | sed 's/^/<DDL>/g'`;
&merror("binlog contain $ddlnum DDL:$MYSQLBINLOG. ddl sql:\n$ddlcnt");
}
return $res;
}
# ----------------------------------------------------------------------------------------
# Func : init all table column order
# if input --database --table params, only get set table column order
# ----------------------------------------------------------------------------------------
sub init_tbcol{
&mdebug("$PRE_FUNCT init_tbcol");
# 提取DML语句
my $cmd .= "$ROLLBACK_DML | grep -E '^(INSERT|UPDATE|DELETE)'";
# 提取表名,并去重
#$cmd .= " | awk '{if (\$1 ~ \"^UPDATE\") {print \$2}else {print \$3}}' | uniq ";
$cmd .= " | awk '{if (\$1 ~ \"^UPDATE\") {print \$2}else {print \$3}}' | sort | uniq ";
&mdebug("get table name cmd\n\t$cmd");
open ALLTABLE, "$cmd | " or die "can't open file:$cmd\n";