返回顶部
首页 > 资讯 > 数据库 >MySQL在ROW模式下如何通过binlog提取SQL语句
  • 974
分享到

MySQL在ROW模式下如何通过binlog提取SQL语句

2024-04-02 19:04:59 974人浏览 安东尼
摘要

小编给大家分享一下Mysql在ROW模式下如何通过binlog提取sql语句,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧! Linux基于row模式的binlo

小编给大家分享一下Mysql在ROW模式下如何通过binlog提取sql语句,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

Linux
基于row模式的binlog,生成DML(insert/update/delete)的rollback语句
通过mysqlbinlog -v 解析binlog生成可读的sql文件
提取需要处理的有效sql
  "### "开头的行.如果输入的start-position位于某个event group中间,则会导致"无法识别event"错误


将INSERT/UPDATE/DELETE 的sql反转,并且1个完整sql只能占1行
  INSERT: INSERT INTO => DELETE FROM, SET => WHERE
  UPDATE: WHERE => SET, SET => WHERE
  DELETE: DELETE FROM => INSERT INTO, WHERE => SET
用列名替换位置@{1,2,3}
  通过desc table获得列顺序及对应的列名
  特殊列类型value做特别处理
逆序


注意:
  表结构与现在的表结构必须相同[谨记]
  由于row模式是幂等的,并且恢复是一次性,所以只提取sql,不提取BEGIN/COMMIT
  只能对INSERT/UPDATE/DELETE进行处理

mysql> select * from yoon;
+----------+------------+-----------+---------------------+
| actor_id | first_name | last_name | last_update         |
+----------+------------+-----------+---------------------+
|        1 | HANK       | YOON      | 2006-02-15 04:34:33 |
|        2 | HANK       | YOON      | 2006-02-15 04:34:33 |
|        3 | HANK       | YOON      | 2006-02-15 04:34:33 |
|        4 | HANK       | YOON      | 2006-02-15 04:34:33 |
|        5 | HANK       | YOON      | 2006-02-15 04:34:33 |
|        6 | HANK       | YOON      | 2006-02-15 04:34:33 |
|        7 | HANK       | YOON      | 2006-02-15 04:34:33 |
|        8 | HANK       | YOON      | 2006-02-15 04:34:33 |
|        9 | HANK       | YOON      | 2006-02-15 04:34:33 |
|       10 | HANK       | YOON      | 2006-02-15 04:34:33 |
|       11 | HANK       | YOON      | 2006-02-15 04:34:33 |
+----------+------------+-----------+---------------------+
11 rows in set (0.00 sec)


mysql> delete from yoon;
Query OK, 11 rows affected (1.03 sec)


mysql> select * from yoon;
Empty set (0.00 sec)

命令之间的空格一定要注意,否则就会无法提取SQL语句:
[root@hank-yoon data]# perl binlog-rollback.pl -f 'mysql-bin.000001' -o '/export/data/mysql/data/yoon.sql' -u 'root' -p 'yoon'
Warning: Using a passWord on the command line interface can be insecure.
[root@hank-yoon data]# ls
auto.cnf            hank     ibdata2      ib_logfile1  modify.pl  mysql-bin.000001  perfORMance_schema  test  yoon.sql
binlog-rollback.pl  ibdata1  ib_logfile0  ib_logfile2  mysql      mysql-bin.index   sakila              yoon
[root@hank-yoon data]# cat yoon.sql 
INSERT INTO `yoon`.`yoon` SET `actor_id`=11, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);
INSERT INTO `yoon`.`yoon` SET `actor_id`=10, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);
INSERT INTO `yoon`.`yoon` SET `actor_id`=9, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);
INSERT INTO `yoon`.`yoon` SET `actor_id`=8, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);
INSERT INTO `yoon`.`yoon` SET `actor_id`=7, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);
INSERT INTO `yoon`.`yoon` SET `actor_id`=6, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);
INSERT INTO `yoon`.`yoon` SET `actor_id`=5, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);
INSERT INTO `yoon`.`yoon` SET `actor_id`=4, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);
INSERT INTO `yoon`.`yoon` SET `actor_id`=3, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);
INSERT INTO `yoon`.`yoon` SET `actor_id`=2, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);
INSERT INTO `yoon`.`yoon` SET `actor_id`=1, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);

mysql> INSERT INTO `yoon`.`yoon` SET `actor_id`=11, `first_name`='HANK', `last_name`='YOON', `last_update`=from_unixtime(1139949273);
Query OK, 1 row affected (0.01 sec)


mysql> select * from yoon;
+----------+------------+-----------+---------------------+
| actor_id | first_name | last_name | last_update         |
+----------+------------+-----------+---------------------+
|       11 | HANK       | YOON      | 2006-02-15 04:34:33 |
+----------+------------+-----------+---------------------+



点击(此处)折叠或打开

  1. #!/usr/lib/perl -w


  2. use strict;

  3. use warnings;


  4. use Class::Struct;

  5. use Getopt::Long qw(:config no_ignore_case);                    # GetOption

  6. # reGISter handler system signals

  7. use sigtrap 'handler', \&sig_int, 'normal-signals';


  8. # catch signal

  9. sub sig_int(){

  10.     my ($signals) = @_;

  11.     print STDERR "# Caught SIG$signals.\n";

  12.     exit 1;

  13. }


  14. my %opt;

  15. my $srcfile;

  16. my $host = '127.0.0.1';

  17. my $port = 3306;

  18. my ($user,$pwd);

  19. my ($MYSQL, $MYSQLBINLOG, $ROLLBACK_DML);

  20. my $outfile = '/dev/null';

  21. my (%do_dbs,%do_tbs);


  22. # tbname=>tbcol, tbcol: @n=>colname,type

  23. my %tbcol_pos;


  24. my $SPLITER_COL = ',';

  25. my $SQLTYPE_IST = 'INSERT';

  26. my $SQLTYPE_UPD = 'UPDATE';

  27. my $SQLTYPE_DEL = 'DELETE';

  28. my $SQLAREA_WHERE = 'WHERE';

  29. my $SQLAREA_SET = 'SET';


  30. my $PRE_FUNCT = '========================== ';


  31. # =========================================================

  32. # 基于row模式的binlog,生成DML(insert/update/delete)的rollback语句

  33. # 通过mysqlbinlog -v 解析binlog生成可读的sql文件

  34. # 提取需要处理的有效sql

  35. #     "### "开头的行.如果输入的start-position位于某个event group中间,则会导致"无法识别event"错误

  36. #

  37. # 将INSERT/UPDATE/DELETE 的sql反转,并且1个完整sql只能占1行

  38. #     INSERT: INSERT INTO => DELETE FROM, SET => WHERE

  39. #     UPDATE: WHERE => SET, SET => WHERE

  40. #     DELETE: DELETE FROM => INSERT INTO, WHERE => SET

  41. # 用列名替换位置@{1,2,3}

  42. #     通过desc table获得列顺序及对应的列名

  43. #     特殊列类型value做特别处理

  44. # 逆序

  45. #

  46. # 注意:

  47. #     表结构与现在的表结构必须相同[谨记]

  48. #     由于row模式是幂等的,并且恢复是一次性,所以只提取sql,不提取BEGIN/COMMIT

  49. #     只能对INSERT/UPDATE/DELETE进行处理

  50. # ========================================================

  51. sub main{


  52.     # get input option

  53.     &get_options();


  54.     #

  55.     &init_tbcol();


  56.     #

  57.     &do_binlog_rollback();

  58. }


  59. &main();



  60. # ----------------------------------------------------------------------------------------

  61. # Func : get options and set option flag

  62. # ----------------------------------------------------------------------------------------

  63. sub get_options{

  64.     #Get options info

  65.     GetOptions(\%opt,

  66.         'help',                    # OUT : print help info

  67.         'f|srcfile=s',            # IN : binlog file

  68.         'o|outfile=s',            # out : output sql file

  69.         'h|host=s',                # IN : host

  70.         'u|user=s', # IN : user

  71.         'p|password=s', # IN : password

  72.         'P|port=i',                # IN : port

  73.         'start-datetime=s',        # IN : start datetime

  74.         'stop-datetime=s',        # IN : stop datetime

  75.         'start-position=i',        # IN : start position

  76.         'stop-position=i',        # IN : stop position

  77.         'd|database=s',            # IN : database, split comma

  78.         'T|table=s',            # IN : table, split comma

  79.         'i|ignore',                # IN : ignore binlog check ddl and so on

  80.         'debug',                # IN : print debug information

  81.      ) or print_usage();


  82.     if (!Scalar(%opt)) {

  83.         &print_usage();

  84.     }


  85.     # Handle for options

  86.     if ($opt{'f'}){

  87.         $srcfile = $opt{'f'};

  88.     }else{

  89.         &merror("please input binlog file");

  90.     }


  91.     $opt{'h'} and $host = $opt{'h'};

  92.     $opt{'u'} and $user = $opt{'u'};

  93.     $opt{'p'} and $pwd = $opt{'p'};

  94.     $opt{'P'} and $port = $opt{'P'};

  95.     if ($opt{'o'}) {

  96.         $outfile = $opt{'o'};

  97.         # 清空 outfile

  98.         `echo '' > $outfile`;

  99.     }


  100.     #

  101.     $MYSQL = qq{mysql -h$host -u$user -p'$pwd' -P$port};

  102.     &mdebug("get_options::MYSQL\n\t$MYSQL");


  103.     # 提取binlog,不需要显示列定义信息,用-v,而不用-vv

  104.     $MYSQLBINLOG = qq{mysqlbinlog -v};

  105.     $MYSQLBINLOG .= " --start-position=".$opt{'start-position'} if $opt{'start-position'};

  106.     $MYSQLBINLOG .= " --stop-position=".$opt{'stop-position'} if $opt{'stop-postion'};

  107.     $MYSQLBINLOG .= " --start-datetime='".$opt{'start-datetime'}."'" if $opt{'start-datetime'};

  108.     $MYSQLBINLOG .= " --stop-datetime='$opt{'stop-datetime'}'" if $opt{'stop-datetime'};

  109.     $MYSQLBINLOG .= " $srcfile";

  110.     &mdebug("get_options::MYSQLBINLOG\n\t$MYSQLBINLOG");


  111.     # 检查binlog中是否含有 ddl sql: CREATE|ALTER|DROP|RENAME

  112.     &check_binlog() unless ($opt{'i'});


  113.     # 不使用mysqlbinlog过滤,USE dbname;方式可能会漏掉某些sql,所以不在mysqlbinlog过滤

  114.     # 指定数据库

  115.     if ($opt{'d'}){

  116.         my @dbs = split(/,/,$opt{'d'});

  117.         foreach my $db (@dbs){

  118.             $do_dbs{$db}=1;

  119.         }

  120.     }


  121.     # 指定表

  122.     if ($opt{'T'}){

  123.         my @tbs = split(/,/,$opt{'T'});

  124.         foreach my $tb (@tbs){

  125.             $do_tbs{$tb}=1;

  126.         }

  127.     }


  128.     # 提取有效DML SQL

  129.     $ROLLBACK_DML = $MYSQLBINLOG." | grep '^### '";

  130.     # 去掉注释: '### ' -> ''

  131.     # 删除首尾空格

  132.     $ROLLBACK_DML .= " | sed 's/###\\s*//g;s/\\s*\$//g'";

  133.     &mdebug("rollback dml\n\t$ROLLBACK_DML");

  134.     

  135.     # 检查内容是否为空

  136.     my $cmd = "$ROLLBACK_DML | wc -l";

  137.     &mdebug("check contain dml sql\n\t$cmd");

  138.     my $size = `$cmd`;

  139.     chomp($size);

  140.     unless ($size >0){

  141.         &merror("binlog DML is empty:$ROLLBACK_DML");

  142.     };


  143. }    



  144. # ----------------------------------------------------------------------------------------

  145. # Func : check binlog contain DDL

  146. # ----------------------------------------------------------------------------------------

  147. sub check_binlog{

  148.     &mdebug("$PRE_FUNCT check_binlog");

  149.     my $cmd = "$MYSQLBINLOG ";

  150.     $cmd .= " | grep -E -i '^(CREATE|ALTER|DROP|RENAME)' ";

  151.     &mdebug("check binlog has DDL cmd\n\t$cmd");

  152.     my $ddlcnt = `$cmd`;

  153.     chomp($ddlcnt);


  154.     my $ddlnum = `$cmd | wc -l`;

  155.     chomp($ddlnum);

  156.     my $res = 0;

  157.     if ($ddlnum>0){

  158.         # 在ddl sql前面加上前缀<DDL>

  159.         $ddlcnt = `echo '$ddlcnt' | sed 's/^//g'`;

  160.         &merror("binlog contain $ddlnum DDL:$MYSQLBINLOG. ddl sql:\n$ddlcnt");

  161.     }


  162.     return $res;

  163. }



  164. # ----------------------------------------------------------------------------------------

  165. # Func : init all table column order

  166. #        if input --database --table params, only get set table column order

  167. # ----------------------------------------------------------------------------------------

  168. sub init_tbcol{

  169.     &mdebug("$PRE_FUNCT init_tbcol");

  170.     # 提取DML语句

  171.     my $cmd .= "$ROLLBACK_DML | grep -E '^(INSERT|UPDATE|DELETE)'";

  172.     # 提取表名,并去重

  173.     #$cmd .= " | awk '{if (\$1 ~ \"^UPDATE\") {print \$2}else {print \$3}}' | uniq ";

  174.     $cmd .= " | awk '{if (\$1 ~ \"^UPDATE\") {print \$2}else {print \$3}}' | sort | uniq ";

  175.     &mdebug("get table name cmd\n\t$cmd");

  176.     open ALLTABLE, "$cmd | " or die "can't open file:$cmd\n";


  177.     while (my $tbname = <ALLTABLE>){

  178.         chomp($tbname);

  179.         #if (exists $tbcol_pos{$tbname}){

  180.         #    next;

  181.         #}

  182.         &init_one_tbcol($tbname) unless (&ignore_tb($tbname));

  183.         

  184.     }

  185.     close ALLTABLE or die "can't close file:$cmd\n";


  186.     # init tb col

  187.     foreach my $tb (keys %tbcol_pos){

  188.         &mdebug("tbname->$tb");

  189.         my %colpos = %{$tbcol_pos{$tb}};

  190.         foreach my $pos (keys %colpos){

  191.             my $col = $colpos{$pos};

  192.             my ($cname,$ctype) = split(/$SPLITER_COL/, $col);

  193.             &mdebug("\tpos->$pos,cname->$cname,ctype->$ctype");

  194.         }

  195.     }

  196. };



  197. # ----------------------------------------------------------------------------------------

  198. # Func : init one table column order

  199. # ----------------------------------------------------------------------------------------

  200. sub init_one_tbcol{

  201.     my $tbname = shift;

  202.     &mdebug("$PRE_FUNCT init_one_tbcol");

  203.     # 获取表结构及列顺序

  204.     my $cmd = $MYSQL." --skip-column-names --silent -e 'desc $tbname'";

  205.     # 提取列名,并拼接

  206.     $cmd .= " | awk -F\'\\t\' \'{print NR\"$SPLITER_COL`\"\$1\"`$SPLITER_COL\"\$2}'";

  207.     &mdebug("get table column infor cmd\n\t$cmd");

  208.     open TBCOL,"$cmd | " or die "can't open desc $tbname;";


  209.     my %colpos;

  210.     while (my $line = <TBCOL>){

  211.         chomp($line);

  212.         my ($pos,$col,$coltype) = split(/$SPLITER_COL/,$line);

  213.         &mdebug("linesss=$line\n\t\tpos=$pos\n\t\tcol=$col\n\t\ttype=$coltype");

  214.         $colpos{$pos} = $col.$SPLITER_COL.$coltype;

  215.     }

  216.     close TBCOL or die "can't colse desc $tbname";


  217.     $tbcol_pos{$tbname} = \%colpos;

  218. }



  219. # ----------------------------------------------------------------------------------------

  220. # Func : rollback sql:    INSERT/UPDATE/DELETE

  221. # ----------------------------------------------------------------------------------------

  222. sub do_binlog_rollback{

  223.     my $binlogfile = "$ROLLBACK_DML ";

  224.     &mdebug("$PRE_FUNCT do_binlog_rollback");


  225.     # INSERT|UPDATE|DELETE

  226.     my $sqltype;

  227.     # WHERE|SET

  228.     my $sqlarea;

  229.     

  230.     my ($tbname, $sqlstr) = ('', '');

  231.     my ($notignore, $isareabegin) = (0,0);


  232.     # output sql file

  233.     open SQLFILE, ">> $outfile" or die "Can't open sql file:$outfile";


  234.     # binlog file

  235.     open BINLOG, "$binlogfile |" or die "Can't open file: $binlogfile";

  236.     while (my $line = <BINLOG>){

  237.         chomp($line);

  238.         if ($line =~ /^(INSERT|UPDATE|DELETE)/){

  239.             # export sql

  240.             if ($sqlstr ne ''){

  241.                 $sqlstr .= ";\n";

  242.                 print SQLFILE $sqlstr;

  243.                 &mdebug("export sql\n\t".$sqlstr);

  244.                 $sqlstr = '';

  245.             }


  246.             if ($line =~ /^INSERT/){

  247.                 $sqltype = $SQLTYPE_IST;

  248.                 $tbname = `echo '$line' | awk '{print \$3}'`;

  249.                 chomp($tbname);

  250.                 $sqlstr = qq{DELETE FROM $tbname};

  251.             }elsif ($line =~ /^UPDATE/){

  252.                 $sqltype = $SQLTYPE_UPD;

  253.                 $tbname = `echo '$line' | awk '{print \$2}'`;

  254.                 chomp($tbname);

  255.                 $sqlstr = qq{UPDATE $tbname};

  256.             }elsif ($line =~ /^DELETE/){

  257.                 $sqltype = $SQLTYPE_DEL;    

  258.                 $tbname = `echo '$line' | awk '{print \$3}'`;

  259.                 chomp($tbname);

  260.                 $sqlstr = qq{INSERT INTO $tbname};

  261.             }


  262.             # check ignore table

  263.             if(&ignore_tb($tbname)){

  264.                 $notignore = 0;

  265.                 &mdebug("#IGNORE#:line:".$line);

  266.                 $sqlstr = '';

  267.             }else{

  268.                 $notignore = 1;

  269.                 &mdebug("#DO#:line:".$line);

  270.             }

  271.         }else {

  272.             if($notignore){

  273.                 &merror("can't get tbname") unless (defined($tbname));

  274.                 if ($line =~ /^WHERE/){

  275.                     $sqlarea = $SQLAREA_WHERE;

  276.                     $sqlstr .= qq{ SET};

  277.                     $isareabegin = 1;

  278.                 }elsif ($line =~ /^SET/){

  279.                     $sqlarea = $SQLAREA_SET;

  280.                     $sqlstr .= qq{ WHERE};

  281.                     $isareabegin = 1;

  282.                 }elsif ($line =~ /^\@/){

  283.                     $sqlstr .= &deal_col_value($tbname, $sqltype, $sqlarea, $isareabegin, $line);

  284.                     $isareabegin = 0;

  285.                 }else{

  286.                     &mdebug("::unknown sql:".$line);

  287.                 }

  288.             }

  289.         }

  290.     }

  291.     # export last sql

  292.     if ($sqlstr ne ''){

  293.         $sqlstr .= ";\n";

  294.         print SQLFILE $sqlstr;

  295.         &mdebug("export sql\n\t".$sqlstr);

  296.     }

  297.     

  298.     close BINLOG or die "Can't close binlog file: $binlogfile";


  299.     close SQLFILE or die "Can't close out sql file: $outfile";


  300.     # 逆序

  301.     # 1!G: 只有第一行不执行G, 将hold space中的内容append回到pattern space

  302.     # h: 将pattern space 拷贝到hold space

  303.     # $!d: 除最后一行都删除

  304.     my $invert = "sed -i '1!G;h;\$!d' $outfile";

  305.     my $res = `$invert`;

  306.     &mdebug("inverter order sqlfile :$invert");

  307. }


  308. # ----------------------------------------------------------------------------------------

  309. # Func : transfer column pos to name

  310. #    deal column value

  311. #

  312. # &deal_col_value($tbname, $sqltype, $sqlarea, $isareabegin, $line);

  313. # ----------------------------------------------------------------------------------------

  314. sub deal_col_value($$$$$){

  315.     my ($tbname, $sqltype, $sqlarea, $isareabegin, $line) = @_;

  316.     &mdebug("$PRE_FUNCT deal_col_value");

  317.     &mdebug("input:tbname->$tbname,type->$sqltype,area->$sqlarea,areabegin->$isareabegin,line->$line");

  318.     my @vals = split(/=/, $line);

  319.     my $pos = substr($vals[0],1);

  320.     my $valstartpos = length($pos)+2;

  321.     my $val = substr($line,$valstartpos);

  322.     my %tbcol = %{$tbcol_pos{$tbname}};

  323.     my ($cname,$ctype) = split(/$SPLITER_COL/,$tbcol{$pos});

  324.     &merror("can't get $tbname column $cname type") unless (defined($cname) || defined($ctype));

  325.     &mdebug("column infor:cname->$cname,type->$ctype");


  326.     # join str

  327.     my $joinstr;

  328.     if ($isareabegin){

  329.         $joinstr = ' ';

  330.     }else{

  331.         # WHERE 被替换为 SET, 使用 , 连接

  332.         if ($sqlarea eq $SQLAREA_WHERE){

  333.             $joinstr = ', ';

  334.         # SET 被替换为 WHERE 使用 AND 连接

  335.         }elsif ($sqlarea eq $SQLAREA_SET){

  336.             $joinstr = ' AND ';

  337.         }else{

  338.             &merror("!!!!!!The scripts error");

  339.         }

  340.     }

  341.     

  342.     #

  343.     my $newline = $joinstr;


  344.     # NULL value

  345.     if (($val eq 'NULL') && ($sqlarea eq $SQLAREA_SET)){

  346.         $newline .= qq{ $cname IS NULL};

  347.     }else{

  348.         # timestamp: record seconds

  349.         if ($ctype eq 'timestamp'){

  350.             $newline .= qq{$cname=from_unixtime($val)};

  351.         # datetime: @n=yyyy-mm-dd hh::ii::ss

  352.         }elsif ($ctype eq 'datetime'){

  353.             $newline .= qq{$cname='$val'};

  354.         }else{

  355.             $newline .= qq{$cname=$val};

  356.         }

  357.     }

  358.     &mdebug("\told>$line\n\tnew>$newline");

  359.     

  360.     return $newline;

  361. }


  362. # ----------------------------------------------------------------------------------------

  363. # Func : check is ignore table

  364. # params: IN table full name #  format:`dbname`.`tbname`

  365. # RETURN:

  366. #        0 not ignore

  367. #        1 ignore

  368. # ----------------------------------------------------------------------------------------

  369. sub ignore_tb($){

  370.     my $fullname = shift;

  371.     # 删除`

  372.     $fullname =~ s/`//g;

  373.     my ($dbname,$tbname) = split(/\./,$fullname);

  374.     my $res = 0;

  375.     

  376.     # 指定了数据库

  377.     if ($opt{'d'}){

  378.         # 与指定库相同

  379.         if ($do_dbs{$dbname}){

  380.             # 指定表

  381.             if ($opt{'T'}){

  382.                 # 与指定表不同

  383.                 unless ($do_tbs{$tbname}){

  384.                     $res = 1;

  385.                 }

  386.             }

  387.         # 与指定库不同

  388.         }else{

  389.             $res = 1;

  390.         }

  391.     }

  392.     #&mdebug("Table check ignore:$fullname->$res");

  393.     return $res;

  394. }



  395. # ----------------------------------------------------------------------------------------

  396. # Func : print debug msg

  397. # ----------------------------------------------------------------------------------------

  398. sub mdebug{

  399.     my (@msg) = @_;

  400.     print "@msg\n" if ($opt{'debug'});

  401. }



  402. # ----------------------------------------------------------------------------------------

  403. # Func : print error msg and exit

  404. # ----------------------------------------------------------------------------------------

  405. sub merror{

  406.     my (@msg) = @_;

  407.     print ":@msg\n";

  408.     &print_usage();

  409.     exit(1);

  410. }


  411. # ----------------------------------------------------------------------------------------

  412. # Func : print usage

  413. # ----------------------------------------------------------------------------------------

  414. sub print_usage{

  415.     print <<EOF;

  416. ==========================================================================================

  417. Command line options :

  418.     --help                # OUT : print help info

  419.     -f, --srcfile            # IN : binlog file. [required]

  420.     -o, --outfile            # OUT : output sql file. [required]

  421.     -h, --host            # IN : host. default '127.0.0.1'

  422.     -u, --user            # IN : user. [required]

  423.     -p, --password            # IN : password. [required]

  424.     -P, --port            # IN : port. default '3306'

  425.     --start-datetime        # IN : start datetime

  426.     --stop-datetime            # IN : stop datetime

  427.     --start-position        # IN : start position

  428.     --stop-position            # IN : stop position

  429.     -d, --database            # IN : database, split comma

  430.     -T, --table            # IN : table, split comma. [required] set -d

  431.     -i, --ignore            # IN : ignore binlog check contain DDL(CREATE|ALTER|DROP|RENAME)

  432.     --debug                # IN : print debug information


  433. Sample :

  434.    shell> perl binlog-rollback.pl -f 'mysql-bin.000001' -o '/tmp/t.sql' -u 'user' -p 'pwd'

  435.    shell> perl binlog-rollback.pl -f 'mysql-bin.000001' -o '/tmp/t.sql' -u 'user' -p 'pwd' -i

  436.    shell> perl binlog-rollback.pl -f 'mysql-bin.000001' -o '/tmp/t.sql' -u 'user' -p 'pwd' --debug

  437.    shell> perl binlog-rollback.pl -f 'mysql-bin.000001' -o '/tmp/t.sql' -h '192.168.1.2' -u 'user' -p 'pwd' -P 3307

  438.    shell> perl binlog-rollback.pl -f 'mysql-bin.000001' -o '/tmp/t.sql' -u 'user' -p 'pwd' --start-position=107

  439.    shell> perl binlog-rollback.pl -f 'mysql-bin.000001' -o '/tmp/t.sql' -u 'user' -p 'pwd' --start-position=107 --stop-position=10000

  440.    shell> perl binlog-rollback.pl -f 'mysql-bin.000001' -o '/tmp/t.sql' -u 'user' -p 'pwd' -d 'db1,db2'

  441.    shell> perl binlog-rollback.pl -f 'mysql-bin.0000*' -o '/tmp/t.sql' -u 'user' -p 'pwd' -d 'db1,db2' -T 'tb1,tb2'

  442. ==========================================================================================

  443. EOF

  444.     exit;

  445. }



  446. 1;

看完了这篇文章,相信你对“MySQL在ROW模式下如何通过binlog提取SQL语句”有了一定的了解,如果想了解更多相关知识,欢迎关注编程网数据库频道,感谢各位的阅读!

您可能感兴趣的文档:

--结束END--

本文标题: MySQL在ROW模式下如何通过binlog提取SQL语句

本文链接: https://lsjlt.com/news/62355.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作