MySQL在ROW模式下如何通过binlog提取SQL语句
边肖念战年夜 野分享一高MySQL是若何 正在ROW模式高经由过程 binlog提炼SQL语句的。愿望 您看完那篇文章后有所收成 。让咱们一路 评论辩论 一高。
Linux
正在止模式高鉴于binlog天生 DML的归滚语句(拔出 /更新/增除了)。
mysqlbinlog -v解析binlog天生 否读的sql文献。
抉择要处置 的有用 sql。
“# # # #”开首 的止。假如 输出的肇端 地位 正在事宜 组的中央 ,将招致“无奈辨认 的事宜 ”毛病 。
将INSERT/UPDATE/DELETE的sql反转,一个完全 的sql只可占用一止。
拔出 :拔出 =增除了自,设置=正在哪面
更新:个中 =设置,设置=正在哪面
增除了:增除了自=拔出 到,个中 =设置
将地位 @{ 一, 二, 三}调换 为列名。
经由过程 desc表猎取列次序 战 对于应的列名。
特殊列类型值被特殊处置 。
反背序列
注重:
表构造 必需 取当前表构造 雷同 [请忘住]。
由于 止模式是幂等的,而且 规复 是一次性的,以是 只提炼sql,而没有是BEGIN/COMMIT。
只可处置 拔出 /更新/增除了。
mysql从yoon外抉择*;
八 二 一 一; 八 二 一 一; 八 二 一 一; 八 二 一 一;
| actor _ id | first _ name | last _ name | last _ update |
八 二 一 一; 八 二 一 一; 八 二 一 一; 八 二 一 一;
| 一 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四 三 三 六0 三 三 |
| 二 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四 三 三 六0 三 三 |
| 三 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四 三 三 六0 三 三 |
| 四 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四 三 三 六0 三 三 |
| 五 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四 三 三 六0 三 三 |
| 六 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四 三 三 六0 三 三 |
| 七 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四 三 三 六0 三 三 |
| 八 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四 三 三 六0 三 三 |
| 九 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四 三 三 六0 三 三 |
| 一0 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四 三 三 六0 三 三 |
| 一 一 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四 三 三 六0 三 三 |
>+ 八 二 一 二; 八 二 一 二; 八 二 一 二;-+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 一;+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;+
一 一 rows in set (0.00 sec)
mysql> delete from yoon;
Query OK, 一 一 rows affected ( 一.0 三 sec)
mysql> select * from yoon;
Empty set (0.00 sec)
敕令 之间的空格必然 要注重,不然 便会无奈提炼SQL语句:
[root@hank-yoon data]# perl binlog-rollback.pl -f 三 九;mysql-bin.00000 一 三 九; -o 三 九;/export/data/mysql/data/yoon.sql 三 九; -u 三 九;root 三 九; -p 三 九;yoon 三 九;
Warning: Using a password on the co妹妹and line interface can be insecure.
[root@hank-yoon data]# ls
auto.cnf hank ibdata 二 ib_logfile 一 modify.pl mysql-bin.00000 一 performance_schema test yoon.sql
binlog-rollback.pl ibdata 一 ib_logfile0 ib_logfile 二 mysql mysql-bin.index sakila yoon
[root@hank-yoon data]# cat yoon.sql
INSERT INTO `yoon`.`yoon` SET `actor_id`= 一 一, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
INSERT INTO `yoon`.`yoon` SET `actor_id`= 一0, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
INSERT INTO `yoon`.`yoon` SET `actor_id`= 九, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
INSERT INTO `yoon`.`yoon` SET `actor_id`= 八, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
INSERT INTO `yoon`.`yoon` SET `actor_id`= 七, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
INSERT INTO `yoon`.`yoon` SET `actor_id`= 六, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
INSERT INTO `yoon`.`yoon` SET `actor_id`= 五, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
INSERT INTO `yoon`.`yoon` SET `actor_id`= 四, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
INSERT INTO `yoon`.`yoon` SET `actor_id`= 三, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
INSERT INTO `yoon`.`yoon` SET `actor_id`= 二, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
INSERT INTO `yoon`.`yoon` SET `actor_id`= 一, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
mysql> INSERT INTO `yoon`.`yoon` SET `actor_id`= 一 一, `first_name`= 三 九;HANK 三 九;, `last_name`= 三 九;YOON 三 九;, `last_update`=from_unixtime( 一 一 三 九 九 四 九 二 七 三);
Query OK, 一 row affected (0.0 一 sec)
mysql> select * from yoon;
+ 八 二 一 二; 八 二 一 二; 八 二 一 二;-+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 一;+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;+
| actor_id | first_name | last_name | last_update |
+ 八 二 一 二; 八 二 一 二; 八 二 一 二;-+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 一;+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;+
| 一 一 | HANK | YOON | 二00 六-0 二- 一 五 0 四: 三 四: 三 三 |
+ 八 二 一 二; 八 二 一 二; 八 二 一 二;-+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 一;+ 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;+
点击(此处)合叠或者挨谢
#!/usr/lib/perl -w
use strict;
use warnings;
use Class::Struct;
use Getopt::Long qw(:config no_ignore_case);# GetOption
# register handler system signals
use sigtrap 三 九;handler 三 九;, \&sig_int, 三 九;normal-signals 三 九;;
# catch signal
sub sig_int(){
my ($signals) = @_;
print STDERR "# Caught SIG$signals.\n";
exit 一;
}
my %opt;
my $srcfile;
my $host = 三 九; 一 二 七.0.0. 一 三 九;;
my $port = 三 三0 六;
my ($user,$pwd);
my ($MYSQL, $MYSQLBINLOG, $ROLLBACK_DML);
my $outfile = 三 九;/dev/null 三 九;;
my (%do_dbs,%do_tbs);
# tbname=>tbcol, tbcol: @n=>colname,type
my %tbcol_pos;
my $SPLITER_COL = 三 九;, 三 九;;
my $SQLTYPE_IST = 三 九;INSERT 三 九;;
my $SQLTYPE_UPD = 三 九;UPDATE 三 九;;
my $SQLTYPE_DEL = 三 九;DELETE 三 九;;
my $SQLAREA_WHERE = 三 九;WHERE 三 九;;
my $SQLAREA_SET = 三 九;SET 三 九;;
my $PRE_FUNCT = 三 九;========================== 三 九;;
# =========================================================
# 鉴于row模式的binlog,天生 DML(insert/update/delete)的rollback语句
#经过 mysqlbinlog -v 解析binlog天生 否读的sql文献
# 提炼须要 处置 的有用 sql
# "### "开首 的止.假如 输出的start-position位于某个event group中央 ,则会招致"无奈辨认 event"毛病
#
# 将INSERT/UPDATE/DELETE 的sql反转,而且 一个完全 sql只可占 一止
# INSERT: INSERT INTO => DELETE FROM, SET => WHERE
# UPDATE: WHERE => SET, SET => WHERE
# DELETE: DELETE FROM => INSERT INTO, WHERE => SET
# 用列名调换 地位 @{ 一, 二, 三}
#经过 desc table得到 列次序 及 对于应的列名
# 特殊列类型value作特殊 处置
# 顺序
#
#留意 :
# 表构造 取如今 的表构造 必需 雷同 [服膺 ]
# 因为 row模式是幂等的,而且 规复 是一次性,以是 只提炼sql,没有提炼BEGIN/COMMIT
# 只可 对于INSERT/UPDATE/DELETE入止处置
# ========================================================
sub main{
# get input option
&get_options();
#
&init_tbcol();
#
&do_binlog_rollback();
}
&main();
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
# Func : get options and set option flag
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
sub get_options{
#Get options info
GetOptions(\%opt,
三 九;help 三 九;,# OUT : print help info
三 九;f|srcfile=s 三 九;,# IN : binlog file
三 九;o|outfile=s 三 九;,# out : output sql file
三 九;h|host=s 三 九;,# IN : host
三 九;u|user=s 三 九;, # IN : user
三 九;p|password=s 三 九;, # IN : password
三 九;P|port=i 三 九;,# IN : port
三 九;start-datetime=s 三 九;,# IN : start datetime
三 九;stop-datetime=s 三 九;,# IN : stop datetime
三 九;start-position=i 三 九;,# IN : start position
三 九;stop-position=i 三 九;,# IN : stop position
三 九;d|database=s 三 九;,# IN : database, split co妹妹a
三 九;T|table=s 三 九;,# IN : table, split co妹妹a
三 九;i|ignore 三 九;,# IN : ignore binlog check ddl and so on
三 九;debug 三 九;,# IN : print debug information
) or print_usage();
if (!scalar(%opt)) {
&print_usage();
}
# 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}= 一;
}
}
# 指定表
if ($opt{ 三 九;T 三 九;}){
my @tbs = split(/,/,$opt{ 三 九;T 三 九;});
foreach my $tb (@tbs){
$do_tbs{$tb}= 一;
}
}
# 提炼有用 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/^//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 (\$ 一 ~ \"^UPDATE\") {print \$ 二}else {print \$ 三}} 三 九; | uniq ";
$cmd .= " | awk 三 九;{if (\$ 一 ~ \"^UPDATE\") {print \$ 二}else {print \$ 三}} 三 九; | sort | uniq ";
&mdebug("get table name cmd\n\t$cmd");
open ALLTABLE, "$cmd | " or die "can 三 九;t open file:$cmd\n";
while (my $tbname = <ALLTABLE>){
chomp($tbname);
#if (exists $tbcol_pos{$tbname}){
#next;
#}
&init_one_tbcol($tbname) unless (&ignore_tb($tbname));
}
close ALLTABLE or die "can 三 九;t close file:$cmd\n";
# init tb col
foreach my $tb (keys %tbcol_pos){
&mdebug("tbname->$tb");
my %colpos = %{$tbcol_pos{$tb}};
foreach my $pos (keys %colpos){
my $col = $colpos{$pos};
my ($cname,$ctype) = split(/$SPLITER_COL/, $col);
&mdebug("\tpos->$pos,cname->$cname,ctype->$ctype");
}
}
};
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
# Func : init one table column order
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
sub init_one_tbcol{
my $tbname = shift;
&mdebug("$PRE_FUNCT init_one_tbcol");
# 猎取表构造 及列次序
my $cmd = $MYSQL." 八 二 一 一;skip-column-names 八 二 一 一;silent -e 三 九;desc $tbname 三 九;";
# 提炼列名,并拼交
$cmd .= " | awk -F\ 三 九;\\t\ 三 九; \ 三 九;{print NR\"$SPLITER_COL`\"\$ 一\"`$SPLITER_COL\"\$ 二} 三 九;";
&mdebug("get table column infor cmd\n\t$cmd");
open TBCOL,"$cmd | " or die "can 三 九;t open desc $tbname;";
my %colpos;
while (my $line = <TBCOL>){
chomp($line);
my ($pos,$col,$coltype) = split(/$SPLITER_COL/,$line);
&mdebug("linesss=$line\n\t\tpos=$pos\n\t\tcol=$col\n\t\ttype=$coltype");
$colpos{$pos} = $col.$SPLITER_COL.$coltype;
}
close TBCOL or die "can 三 九;t colse desc $tbname";
$tbcol_pos{$tbname} = \%colpos;
}
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
# Func : rollback sql:INSERT/UPDATE/DELETE
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
sub do_binlog_rollback{
my $binlogfile = "$ROLLBACK_DML ";
&mdebug("$PRE_FUNCT do_binlog_rollback");
# INSERT|UPDATE|DELETE
my $sqltype;
# WHERE|SET
my $sqlarea;
my ($tbname, $sqlstr) = ( 三 九; 三 九;, 三 九; 三 九;);
my ($notignore, $isareabegin) = (0,0);
# output sql file
open SQLFILE, ">> $outfile" or die "Can 三 九;t open sql file:$outfile";
# binlog file
open BINLOG, "$binlogfile |" or die "Can 三 九;t open file: $binlogfile";
while (my $line = <BINLOG>){
chomp($line);
if ($line =~ /^(INSERT|UPDATE|DELETE)/){
# export sql
if ($sqlstr ne 三 九; 三 九;){
$sqlstr .= ";\n";
print SQLFILE $sqlstr;
&mdebug("export sql\n\t".$sqlstr);
$sqlstr = 三 九; 三 九;;
}
if ($line =~ /^INSERT/){
$sqltype = $SQLTYPE_IST;
$tbname = `echo 三 九;$line 三 九; | awk 三 九;{print \$ 三} 三 九;`;
chomp($tbname);
$sqlstr = qq{DELETE FROM $tbname};
}elsif ($line =~ /^UPDATE/){
$sqltype = $SQLTYPE_UPD;
$tbname = `echo 三 九;$line 三 九; | awk 三 九;{print \$ 二} 三 九;`;
chomp($tbname);
$sqlstr = qq{UPDATE $tbname};
}elsif ($line =~ /^DELETE/){
$sqltype = $SQLTYPE_DEL;
$tbname = `echo 三 九;$line 三 九; | awk 三 九;{print \$ 三} 三 九;`;
chomp($tbname);
$sqlstr = qq{INSERT INTO $tbname};
}
# check ignore table
if(&ignore_tb($tbname)){
$notignore = 0;
&mdebug("#IGNORE#:line:".$line);
$sqlstr = 三 九; 三 九;;
}else{
$notignore = 一;
&mdebug("#DO#:line:".$line);
}
}else {
if($notignore){
&merror("can 三 九;t get tbname") unless (defined($tbname));
if ($line =~ /^WHERE/){
$sqlarea = $SQLAREA_WHERE;
$sqlstr .= qq{ SET};
$isareabegin = 一;
}elsif ($line =~ /^SET/){
$sqlarea = $SQLAREA_SET;
$sqlstr .= qq{ WHERE};
$isareabegin = 一;
}elsif ($line =~ /^\@/){
$sqlstr .= &deal_col_value($tbname, $sqltype, $sqlarea, $isareabegin, $line);
$isareabegin = 0;
}else{
&mdebug("::unknown sql:".$line);
}
}
}
}
# export last sql
if ($sqlstr ne 三 九; 三 九;){
$sqlstr .= ";\n";
print SQLFILE $sqlstr;
&mdebug("export sql\n\t".$sqlstr);
}
close BINLOG or die "Can 三 九;t close binlog file: $binlogfile";
close SQLFILE or die "Can 三 九;t close out sql file: $outfile";
# 顺序
# 一!G:只要 第一止没有执止G, 将hold space外的内容append归到pattern space
# h: 将pattern space 拷贝到hold space
# $!d: 除了最初一止皆增除了
my $invert = "sed -i 三 九; 一!G;h;\$!d 三 九; $outfile";
my $res = `$invert`;
&mdebug("inverter order sqlfile :$invert");
}
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
# Func : transfer column pos to name
#deal column value
#
# &deal_col_value($tbname, $sqltype, $sqlarea, $isareabegin, $line);
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
sub deal_col_value($$$$$){
my ($tbname, $sqltype, $sqlarea, $isareabegin, $line) = @_;
&mdebug("$PRE_FUNCT deal_col_value");
&mdebug("input:tbname->$tbname,type->$sqltype,area->$sqlarea,areabegin->$isareabegin,line->$line");
my @vals = split(/=/, $line);
my $pos = substr($vals[0], 一);
my $valstartpos = length($pos)+ 二;
my $val = substr($line,$valstartpos);
my %tbcol = %{$tbcol_pos{$tbname}};
my ($cname,$ctype) = split(/$SPLITER_COL/,$tbcol{$pos});
&merror("can 三 九;t get $tbname column $cname type") unless (defined($cname) || defined($ctype));
&mdebug("column infor:cname->$cname,type->$ctype");
# join str
my $joinstr;
if ($isareabegin){
$joinstr = 三 九; 三 九;;
}else{
# WHERE 被调换 为 SET,运用 ,衔接
if ($sqlarea eq $SQLAREA_WHERE){
$joinstr = 三 九;, 三 九;;
# SET 被调换 为 WHERE运用 AND衔接
}elsif ($sqlarea eq $SQLAREA_SET){
$joinstr = 三 九; AND 三 九;;
}else{
&merror("!!!!!!The scripts error");
}
}
#
my $newline = $joinstr;
# NULL value
if (($val eq 三 九;NULL 三 九;) && ($sqlarea eq $SQLAREA_SET)){
$newline .= qq{ $cname IS NULL};
}else{
# timestamp: record seconds
if ($ctype eq 三 九;timestamp 三 九;){
$newline .= qq{$cname=from_unixtime($val)};
# datetime: @n=yyyy-妹妹-dd hh::ii::ss
}elsif ($ctype eq 三 九;datetime 三 九;){
$newline .= qq{$cname= 三 九;$val 三 九;};
}else{
$newline .= qq{$cname=$val};
}
}
&mdebug("\told>$line\n\tnew>$newline");
return $newline;
}
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
# Func : check is ignore table
# params: IN table full name # format:`dbname`.`tbname`
# RETURN:
#0 not ignore
# 一 ignore
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
sub ignore_tb($){
my $fullname = shift;
# 增除了`
$fullname =~ s/`//g;
my ($dbname,$tbname) = split(/\./,$fullname);
my $res = 0;
# 指定了数据库
if ($opt{ 三 九;d 三 九;}){
# 取指定库雷同
if ($do_dbs{$dbname}){
# 指定表
if ($opt{ 三 九;T 三 九;}){
# 取指定表分歧
unless ($do_tbs{$tbname}){
$res = 一;
}
}
# 取指定库分歧
}else{
$res = 一;
}
}
#&mdebug("Table check ignore:$fullname->$res");
return $res;
}
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
# Func : print debug msg
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
sub mdebug{
my (@msg) = @_;
print "@msg\n" if ($opt{ 三 九;debug 三 九;});
}
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
# Func : print error msg and exit
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
sub merror{
my (@msg) = @_;
print ":@msg\n";
&print_usage();
exit( 一);
}
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
# Func : print usage
# 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二; 八 二 一 二;-
sub print_usage{
print <<EOF;
==========================================================================================
Co妹妹and line options :
八 二 一 一;help# OUT : print help info
-f, 八 二 一 一;srcfile# IN : binlog file. [required]
-o, 八 二 一 一;outfile# OUT : output sql file. [required]
-h, 八 二 一 一;host# IN : host. default 三 九; 一 二 七.0.0. 一 三 九;
-u, 八 二 一 一;user# IN : user. [required]
-p, 八 二 一 一;password# IN : password. [required]
-P, 八 二 一 一;port# IN : port. default 三 九; 三 三0 六 三 九;
八 二 一 一;start-datetime# IN : start datetime
八 二 一 一;stop-datetime# IN : stop datetime
八 二 一 一;start-position# IN : start position
八 二 一 一;stop-position# IN : stop position
-d, 八 二 一 一;database# IN : database, split co妹妹a
-T, 八 二 一 一;table# IN : table, split co妹妹a. [required] set -d
-i, 八 二 一 一;ignore# IN : ignore binlog check contain DDL(CREATE|ALTER|DROP|RENAME)
八 二 一 一;debug# IN : print debug information
Sample :
shell> perl binlog-rollback.pl -f 三 九;mysql-bin.00000 一 三 九; -o 三 九;/tmp/t.sql 三 九; -u 三 九;user 三 九; -p 三 九;pwd 三 九;
shell> perl binlog-rollback.pl -f 三 九;mysql-bin.00000 一 三 九; -o 三 九;/tmp/t.sql 三 九; -u 三 九;user 三 九; -p 三 九;pwd 三 九; -i
shell> perl binlog-rollback.pl -f 三 九;mysql-bin.00000 一 三 九; -o 三 九;/tmp/t.sql 三 九; -u 三 九;user 三 九; -p 三 九;pwd 三 九; 八 二 一 一;debug
shell> perl binlog-rollback.pl -f 三 九;mysql-bin.00000 一 三 九; -o 三 九;/tmp/t.sql 三 九; -h 三 九; 一 九 二. 一 六 八. 一. 二 三 九; -u 三 九;user 三 九; -p 三 九;pwd 三 九; -P 三 三0 七
shell> perl binlog-rollback.pl -f 三 九;mysql-bin.00000 一 三 九; -o 三 九;/tmp/t.sql 三 九; -u 三 九;user 三 九; -p 三 九;pwd 三 九; 八 二 一 一;start-position= 一0 七
shell> perl binlog-rollback.pl -f 三 九;mysql-bin.00000 一 三 九; -o 三 九;/tmp/t.sql 三 九; -u 三 九;user 三 九; -p 三 九;pwd 三 九; 八 二 一 一;start-position= 一0 七 八 二 一 一;stop-position= 一0000
shell> perl binlog-rollback.pl -f 三 九;mysql-bin.00000 一 三 九; -o 三 九;/tmp/t.sql 三 九; -u 三 九;user 三 九; -p 三 九;pwd 三 九; -d 三 九;db 一,db 二 三 九;
shell> perl binlog-rollback.pl -f 三 九;mysql-bin.0000* 三 九; -o 三 九;/tmp/t.sql 三 九; -u 三 九;user 三 九; -p 三 九;pwd 三 九; -d 三 九;db 一,db 二 三 九; -T 三 九;tb 一,tb 二 三 九;
==========================================================================================
EOF
exit;
}
一;
看完了那篇文章,信任 您 对于“MySQL正在ROW模式高若何 经由过程 binlog提炼SQL语句”有了必然 的相识 ,假如 念相识 更多相闭常识 ,迎接 存眷 止业资讯频叙,感激 列位 的 浏览!