File: filter_mysqlbinlog

package info (click to toggle)
mha4mysql-node 0.58-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 240 kB
  • sloc: perl: 2,648; makefile: 9
file content (159 lines) | stat: -rwxr-xr-x 4,807 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/env perl

#  Copyright (C) 2011 DeNA Co.,Ltd.
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#  Foundation, Inc.,
#  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use strict;
use warnings FATAL => 'all';

use English qw(-no_match_vars);
use Getopt::Long;
use Pod::Usage;
use MHA::NodeConst;

GetOptions(
  \my %opt, qw/
    help
    version
    /,
) or pod2usage(1);

if ( $opt{help} ) {
  pod2usage(0);
}

if ( $opt{version} ) {
  print "filter_mysqlbinlog version $MHA::NodeConst::VERSION.\n";
  exit 0;
}

my $line;
my @rows_buf      = ();
my $parsed_events = 0;

sub read_line() {
  if ( $line = <STDIN> ) {
    push @rows_buf, $line;
    return $line;
  }
  else {
    return;
  }
}

sub print_rows() {
  foreach (@rows_buf) {
    print $_;
  }
  @rows_buf = ();
  return 0;
}

while ( $line = read_line() ) {

  if ( $line =~ m/^# at \d+\n$/ ) {
    $parsed_events++;
    do {
      read_line();
    } while ( ( $line =~ m/^# at \d+\n$/ ) && !print_rows() );

   # Remove ROLLBACK statement and equivalent BINLOG statement in a START event.
   # START event should show up at the beginning of the binary/relay logs,
   # so ignore it if enough binlog events are already parsed.
    if ( $line =~ m/^#.*?Start: binlog v.*?created.*\n$/
      && $parsed_events < 10 )
    {
      read_line();
      if ( $line =~ m/^# Warning: this binlog .*\n$/ ) {
        read_line();
      }
      if ( $line =~ m/^ROLLBACK.*\n$/ ) {
        pop @rows_buf;
        push @rows_buf,
"# ROLLBACK and BINLOG events generated by start_event were trimmed.\n";
        read_line();
        while ( !( $line =~ m/(^# at \d+\n$)|(^DELIMITER ;\n$)/ ) ) {
          pop @rows_buf;
          read_line();
        }
      }
    }
    print_rows();
  }

  # Trim a tail ROLLBACK statement. mysqlbinlog adds the following statements
  # at the tail of the output, if neither --disable-log-bin nor --set-charset
  # was set.
  #   # End of log file
  #   ROLLBACK /* added by mysqlbinlog */;
  #   /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
  elsif ( $line =~ m/^# End of log file\n$/ ) {
    read_line();
    if ( $line =~ m/^ROLLBACK \/\* added by mysqlbinlog \*\/;\n$/ ) {
      read_line();
      if ( $line =~
        m/^\/\*!50003 SET COMPLETION_TYPE=\@OLD_COMPLETION_TYPE\*\/;\n$/ )
      {
        if ( !read_line() ) {
          pop @rows_buf;
          pop @rows_buf;
          push @rows_buf,
            "# Tail ROLLBACK event generated by mysqlbinlog was trimmed.\n";
          goto EOF;
        }
      }
    }
    print_rows();
  }
  else {
    print_rows();
  }
}

EOF:
print_rows();

exit 0;

# ############################################################################
# Documentation
# ############################################################################

=pod

=head1 NAME

filter_mysqlbinlog - Trimming ROLLBACK statements and equivalent BINLOG events added by mysqlbinlog. This script is now obsolete.

=head1 SYNOPSIS

mysqlbinlog binary_or_relay_log_file | filter_mysqlbinlog

Note that this script is now obsolete and not used by MHA by default.

=head1 DESCRIPTION

mysqlbinlog command provided by Oracle implicitly adds ROLLBACK statements and equivalent BINLOG events. But this causes problems when recovering slave servers. To recover slaves, MHA might need to apply the following binlog events.
 1) Relay log events from Relay_Log_Pos to the end of the relay log file
 2) Differential relay log events from the latest slave
 3) Differential binary log events from the dead master
mysqlbinlog command needs to be executed on these files separately. If a transaction does not end by 1) or 2), implicit ROLLBACK event rolls back the transaction, which will result in inconsistency.
filter_mysqlbinlog is a tool to fix this issue. 
Note that ROLLBACK statements themselves are added in usual situations. For example, when you execute 1. BEGIN; 2. Updating transactional tables 3. Updating non-transactional tables  4. ROLLBACK, a ROLLBACK statement is written to the binary log to rollback transactional queries. This is normal situation so filter_mysqlbinlog must not remove all ROLLBACK events.

Note that this script is now obsolete and not used by MHA by default.