File: ndb_binlog_check_binlog_index.inc

package info (click to toggle)
mysql-8.0 8.0.43-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,273,924 kB
  • sloc: cpp: 4,684,605; ansic: 412,450; pascal: 108,398; java: 83,641; perl: 30,221; cs: 27,067; sql: 26,594; sh: 24,181; python: 21,816; yacc: 17,169; php: 11,522; xml: 7,388; javascript: 7,076; makefile: 2,194; lex: 1,075; awk: 670; asm: 520; objc: 183; ruby: 97; lisp: 86
file content (272 lines) | stat: -rw-r--r-- 9,336 bytes parent folder | download
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
#
# ndb_binlog_check_binlog_index
#
# This include file determines epoch boundaries from a Binlog using the
# mysqlbinlog tool
# It then compares the calculated boundaries with the contents of
# the ndb_binlog_index table
# The intention is to prove that :
#   - for any epoch A
#     - The mysql.ndb_binlog_index next pos for A is the first binlog location
#       after the COMMIT event of epoch A
#   - Therefore the presence of a committed epoch number in a slave cluster's
#     ndb_apply_status table is taken to mean only that the transaction which
#     wrote it committed.
#   - The Slave should resume immediately after the committed transaction
# Note that :
#   - The start position (Position, File) is vaguely defined and can refer
#     to any position after the previously committed epoch's COMMIT event
#     and before the epoch's BEGIN event.  A test and fix for this
#     exists, but has been shelved.
#

--disable_query_log
set sql_log_bin=0;

let have_next_pos=query_get_value(select count(1) as have_next_file from information_schema.COLUMNS where table_schema='mysql' and table_name='ndb_binlog_index' and column_name='next_file', have_next_file, 1);
if (!$have_next_pos)
{
  --echo Nothing to verify
}
if ($have_next_pos)
{

  let $MYSQLD_DATADIR= `select @@datadir;`;
  let $tmp_file = $MYSQLTEST_VARDIR/tmp/ndb_binlog_mysqlbinlog.sql;
  --exec $MYSQL_BINLOG --verbose $MYSQLD_DATADIR/binlog.000001 > $tmp_file

  create table raw_binlog_rows(
    txt varchar(1000) character set latin1
  );

  --eval load data local infile '$tmp_file' into table raw_binlog_rows columns terminated by '\n';
  --remove_file $tmp_file

  #select count(*) FROM raw_binlog_rows;

  create table binlog_stmt_parts_unassoc(
    txt varchar(1000) character set latin1,
    line_count int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    stmt_boundary int,
    tx_boundary int
  );

  # Auto incrementing line_count values preserve the order of the raw binlog rows.
  # Use replace() here to get rid of any unwanted Windows
  # CRs
  insert into binlog_stmt_parts_unassoc (txt,stmt_boundary,tx_boundary)
    select replace(txt, '\r', ''),
           (txt like '%INSERT%' or         # Identify statement boundaries
            txt like '%UPDATE%' or
            txt like '%DELETE%' or
            txt = 'BEGIN' or
            txt = 'COMMIT'),
           txt = 'BEGIN'             # Transaction boundary
      from raw_binlog_rows
      where
        txt like '###%' OR
        txt = 'BEGIN' OR
        txt = 'COMMIT' OR
        txt like '%# at%';   # Discard stuff we don't care about

  #select * from binlog_stmt_parts_unassoc;

  create table binlog_stmt_parts_assoc(
    txt varchar(1000) character set latin1,
    line_count int,
    stmt_num int,
    tx_num int,
    key(stmt_num),
    key(line_count),
    key(txt)
  );

  insert into binlog_stmt_parts_assoc
  (  select txt,
            line_count,
            SUM(stmt_boundary) OVER(ORDER BY line_count) AS stmt_count, # All rows from same stmt will
                                                                        # have same stmt_num
            SUM(tx_boundary) OVER(ORDER BY line_count) AS tx_count      # Same transaction
        from binlog_stmt_parts_unassoc order by line_count);

  create table apply_status_stmt_nums (stmt_num int primary key);

  insert into apply_status_stmt_nums
    select stmt_num from binlog_stmt_parts_assoc
    where txt like '%INSERT INTO mysql.ndb_apply_status%';

  create table relevant_info(
    txt varchar(1000) character set latin1,
    tx_num int,
    line_count int
  );

  insert into relevant_info
    # Epoch number to tx_num mapping
    #  ###  @2= <epoch>, <tx_num>, <line_count>
    select bspa.txt, bspa.tx_num, bspa.line_count
    from
      binlog_stmt_parts_assoc as bspa,
      apply_status_stmt_nums
    where
      (bspa.stmt_num = apply_status_stmt_nums.stmt_num
           and
       bspa.txt like '%@2=%')                # Epoch number
  union
    # BEGIN and COMMIT event to tx_num and file position mapping
    # BEGIN # at <offset>, <tx_num>, <line_count>
    # COMMIT # at <offset>, <tx_num>, <line_count>
    #
    select concat(bspa2.txt, " ", bspa1.txt), bspa2.tx_num, bspa1.line_count
    from
      binlog_stmt_parts_assoc as bspa1,
      binlog_stmt_parts_assoc as bspa2
    where
      (bspa2.txt = 'BEGIN' and
       bspa1.line_count = bspa2.line_count - 1) # Line before BEGIN event
      or
      (bspa2.txt = 'COMMIT' and
       bspa1.line_count = bspa2.line_count + 1); # Line after COMMIT event

  #select * from relevant_info order by line_count;

  create table epoch_info (num int NOT NULL AUTO_INCREMENT PRIMARY KEY, epoch bigint, start_pos bigint, next_pos bigint);
  set @epoch_num=0;

  insert into epoch_info (epoch , start_pos , next_pos)
    select
    (right(ri1.txt, length(ri1.txt) - length('###   @2='))) + 0, # epoch number
     (right(ri2.txt, length(ri2.txt) - length('BEGIN # at '))) + 0, # start pos
      (right(ri3.txt, length(ri3.txt) - length('COMMIT # at '))) + 0  # end pos
    from
      relevant_info as ri1, relevant_info as ri2, relevant_info as ri3
    where
      ri1.tx_num = ri2.tx_num
      and
      ri1.tx_num = ri3.tx_num
      and
      ri1.txt like '%@2=%'
      and
      ri2.txt like '%BEGIN%'
      and
      ri3.txt like '%COMMIT%';

  #select * from epoch_info order by num;

  # Insert dummy row 0 to give start pos of first epoch
  --let $first_event_pos= query_get_value(SHOW BINLOG EVENTS LIMIT 1, End_log_pos, 1)
  eval insert into epoch_info values (0,0,0,$first_event_pos);


  # Get epoch info where following epoch starts at end of previous epoch
  create table adjusted_epoch_info (epoch bigint, start_pos bigint);

  insert into adjusted_epoch_info
    select e2.epoch, e1.next_pos as start_pos
      from
        epoch_info as e1, epoch_info as e2
      where
        e2.num = e1.num + 1;

  #select * from adjusted_epoch_info;

  # Should not return any rows
  --echo ---------------------------------------------------------------------------
  --echo Mismatches between Binlog index next_pos and Binlog COMMIT event pos
  --echo ---------------------------------------------------------------------------

  select binlog.epoch,
           binlog.next_pos as calculated_pos,
           binlog_index.next_position as stored_pos
    from epoch_info as binlog,
           mysql.ndb_binlog_index as binlog_index
    where binlog.epoch = binlog_index.epoch AND
            binlog.next_pos != binlog_index.next_position;

  --echo Done

  # Following commented out as it is an (understandably) non-deterministic
  # race
  #
  #--echo ----------------------------------------------
  #--echo Any gaps between epoch n next_pos and epoch n+1 start_pos
  #--echo ----------------------------------------------
  ## This indicates that other events (e.g. DDL) were inserted between the end of
  ## one epoch and the recorded start pos of the next epoch
  ##select binlog.epoch,
  ##         binlog.start_pos as calculated_start_pos,
  ##         bi.Position as stored_start_pos
  #select count(1) > 0
  #  from
  #    adjusted_epoch_info as binlog,
  #    mysql.ndb_binlog_index as bi
  #  where
  #    binlog.epoch = bi.epoch
  #    and
  #    binlog.start_pos != bi.Position;
  #
  #--echo Done

  # Following is commented out as it is an (understandably) non-deterministic
  # race
  #
  #--echo -----------------------------------------------
  #--echo Any stored start positions different to BEGIN positions
  #--echo -----------------------------------------------
  ## This indicates that other events (e.g. DDL) were inserted between the recorded
  ## start of an epoch, and the actual start of the transaction (BEGIN)
  ##
  ##select binlog.epoch,
  ##         binlog.start_pos as calculated_pos,
  ##         binlog_index.position as stored_pos
  #select count(1) > 0
  #  from epoch_info as binlog,
  #         mysql.ndb_binlog_index as binlog_index
  #  where binlog.epoch = binlog_index.epoch AND
  #          binlog.start_pos != binlog_index.position;
  #
  #--echo Done

  # The following test is no longer relevant as epochs are
  # not guaranteed adjacent.
  #
  #create table bi_offsets (count bigint,
  #                              epoch bigint,
  #                              start_pos bigint,
  #                              next_pos bigint);

  #set @epoch_count=0;

  #insert into bi_offsets
  #  select @epoch_count:=@epoch_count+1,
  #    epoch, Position, next_position
  #    from mysql.ndb_binlog_index
  #    order by epoch asc;

  #select * from bi_offsets order by epoch;

  #--echo ----------------------------------------
  #--echo Non adjacent epochs in ndb_binlog_index
  #--echo ----------------------------------------

  #select bio1.count, bio1.epoch, bio1.start_pos, bio1.next_pos,
  #         bio2.count, bio2.epoch, bio2.start_pos, bio2.next_pos
  #  from bi_offsets as bio1, bi_offsets as bio2
  #  where
  #    bio2.count = bio1.count + 1 AND
  #    bio2.start_pos != bio1.next_pos;

  #--echo Done.

  #drop table bi_offsets;

  drop table adjusted_epoch_info;
  drop table epoch_info;
  drop table relevant_info;
  drop table apply_status_stmt_nums;
  drop table binlog_stmt_parts_assoc;
  drop table binlog_stmt_parts_unassoc;
  drop table raw_binlog_rows;
}
set sql_log_bin=1;
--enable_query_log