mysql使用binlog恢复数据 Thursday, August 21, 2014 9:29 AM ###############################方法一############################ #!/bin/bash mpath=”/data1/mysql5022_3306/binlog”

for ((a=989;a < 1360;a++))

do

if [[ $a -lt 1000 ]];then

b=”0$a”

else

b=$a

fi

filename=”${mpath}/mysql-log.00${b}”

if [[ -f $filename ]];then

echo “$filename” #mysqlbinlog ${filename} >temp.log #由于之上语句没有指定临时文件目录,所以大量临时数据会产生在/tmp下,容易引起磁盘爆满。使用下句: mysqlbinlog –local-load=/data1/mysql5022_3306/tmp ${filename} >temp.log cat temp.log|grep “version_property” »result.log

fi

done

########################方法二########################## #!/usr/bin/perl

#################################################################

#parse_binlog.pl: find proper mysql binlog file and print lines

match a giving regex.

#Author: Curu Wong

#License: GPL v2

#Date: 2012-10-31

#################################################################

use strict;

use warnings;

use File::Glob ‘:glob’;

use File::stat ;

use Getopt::Long;

sub parse_time{

my $time_str = shift;

my $ts = qx(date -d “$time_str” +%s);

return $ts;

}

#return file atime and mtime

sub get_amtime{

my $file = shift;

my $stat = stat($file);

return ($stat->atime,$stat->mtime);

}

sub select_binlog_files{

#$logbin is mysql –log-bin param

my $logbin = shift;

my $time_start = shift;

my $time_end = shift;

my @result;

my @files = bsd_glob(“$logbin.[0-9]*”);

for my $f (@files){

my ($atime, $mtime) = get_amtime($f);

push @result, $f if ($mtime >= $time_start & & $atime < = $time_end);

}

return @result;

}

sub get_sql_from_binlog{

my $time_start = shift;

my $time_end = shift;

my $db = shift;

my $tbl = shift;

my @binlogfiles = @_;

my $mysqlbinlog_cmd=”mysqlbinlog –start-datetime=’$time_start’ –stop-datetime=’$time_end’ @binlogfiles”;

print STDERR “$mysqlbinlog_cmd\n”;

open(my $BINLOG, “$mysqlbinlog_cmd ”)

or die “unable to run mysqlbinlog:$!”;

#separate record by binlog header

my $record_sep = “# at “;

local $/ = “\n$record_sep”;

my $cur_db = “”;

my $use_db = 0;

print ‘*’ x 80,”\n”;

print “db:$db, tbl:$tbl\n”;

print ‘*’ x 80,”\n”;

my @tbl_regex = (

qr/^\sCREATE\s+(?:TEMPORARY)?\sTABLE\s(?:IF\s+NOT\s+EXISTS)?\s`?\b$tbl\b’?/i,

qr/^\sALTER\s+(?:IGNORE)?\sTABLE\s+?\b$tbl\b?/i,

qr/^\s*(?:CREATE DROP).+?\s+INDEX\s+.*?\s+ON\s+?\b$tbl\b?/i,

qr/^\sDROP\s+(?:TEMPORARY)?\sTABLE\s+.*??\b$tbl\b?/i,

qr/^\sRENAME\s+TABLE.?\b$tbl\b/i,

qr/^\sTRUNCATE\s+(?:TABLE)?\s?\b$tbl\b?/i,

qr/^\sDELETE.?\s+FROM\s+?\b$tbl\b?/i,

qr/^\s*(?:INSERT REPLACE)\s+(?:LOW_PRIORITY DELAYED HIGH_PRIORITY)?(?:\s+IGNORE)?(?:INTO\s+)?\s*?\b$tbl\b?/i,

qr/^\sLOAD\s+DATA.?INTO\s+TABLE\s+?\b$tbl\b?/i,

qr/^\sUPDATE\s+.??\b$tbl\b?/i,

);

while(my $record = < $BINLOG>){

#skip next 2 line

$record = substr($record, index($record, “\n”) + 1);

$record = substr($record, index($record, “\n”) + 1);

my @statements = split /;\n/, $record;

for my $stmt (@statements){

if($stmt =~ /use\s+?(\S+)?/){

$cur_db = $1;

$use_db = 1;

}

next if($db & & ($db ne $cur_db));

if($use_db){

$use_db = 0;

print “$stmt;\n”;

next;

}

print “$stmt;\n” if (!$tbl or grep { $stmt =~ m/$_/ } @tbl_regex);

}

}

close($BINLOG);

}

sub usage{

print “Usage: $0 [-i] < log-bin> < start_time> < stop_time> < db_name> [tbl_name]\n”;

print “eg:\n”;

print “ $0 /var/lib/mysql/mysql-bin ‘2012-10-20 00:00:00’ ‘2012-10-21 00:00:00’ ‘d_qqpcmgr_crash_raw’\n”;

print “\n”;

print “Note: < start_time> or < stop_time> must be in valid mysql DATETIME or TIMESTAMP format\n”;

print “ use -i option to ignore case in < regex>\n”;

print “ < log-bin> is the full file prefix of mysql binlog,not just filename prefix\n”;

exit(1);

}

#main

my $ignore_case = 0;

#parse options

GetOptions(‘help|h’ =>
& usage,

);

if(@ARGV < 5){

usage();

}

my ($dir, $time_start, $time_end, $db, $tbl) = @ARGV;

my @binlog = select_binlog_files($dir, parse_time($time_start), parse_time($time_end));

get_sql_from_binlog($time_start, $time_end, $db, $tbl, @binlog);

已使用 Microsoft OneNote 2016 创建。