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
|
--source include/have_binlog_format_mixed.inc
SET GLOBAL binlog_gtid_index= 0;
SET GLOBAL binlog_gtid_index= 1;
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
--let $pos1= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid1= @@gtid_binlog_pos;
CREATE TABLE t1 (a INT PRIMARY KEY);
--let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid2= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (1);
--let $pos3= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid3= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (2);
INSERT INTO t1 VALUES (3);
INSERT INTO t1 VALUES (4);
--let $pos4= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid4= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (5);
--let $pos5= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid5= @@gtid_binlog_pos;
--disable_query_log
--let $i=0
while ($i < 100) {
eval INSERT INTO t1 VALUES (6 + $i);
inc $i;
}
--enable_query_log
--let $pos6= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid6= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (106);
INSERT INTO t1 VALUES (107);
# Test first the hot and then the cold index.
--let $i= 0
while ($i < 2) {
--disable_query_log
eval SELECT BINLOG_GTID_POS('$file', $pos1) = @gtid1 AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos2) = @gtid2 AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos3) = @gtid3 AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos4) = @gtid4 AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos5) = @gtid5 AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos6) = @gtid6 AS Ok;
--enable_query_log
inc $i;
if ($i == 1) {
FLUSH BINARY LOGS;
}
}
--echo *** Test that purge deletes the gtid index files. ***
FLUSH BINARY LOGS;
INSERT INTO t1 VALUES (200);
--let $file2= query_get_value(SHOW MASTER STATUS, File, 1)
FLUSH BINARY LOGS;
INSERT INTO t1 VALUES (201);
--let $file3= query_get_value(SHOW MASTER STATUS, File, 1)
FLUSH BINARY LOGS;
INSERT INTO t1 VALUES (202);
--let $file4= query_get_value(SHOW MASTER STATUS, File, 1)
--replace_result $file3 FILE
eval PURGE BINARY LOGS TO '$file3';
--let $MYSQLD_DATADIR= `select @@datadir`
--error 1
--file_exists $MYSQLD_DATADIR/$file.idx
--error 1
--file_exists $MYSQLD_DATADIR/$file2.idx
--file_exists $MYSQLD_DATADIR/$file3.idx
--file_exists $MYSQLD_DATADIR/$file4.idx
--echo *** Test missed index lookup due to missing or corrupt index file.
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
INSERT INTO t1 VALUES (301);
INSERT INTO t1 VALUES (302);
INSERT INTO t1 VALUES (303);
--let $pos= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid_pos= @@GLOBAL.gtid_binlog_pos;
INSERT INTO t1 VALUES (304);
INSERT INTO t1 VALUES (305);
# BINLOG_GTID_POS() has a side effect: it increments binlog_gtid_index_hit
--disable_ps2_protocol
FLUSH NO_WRITE_TO_BINLOG GLOBAL STATUS;
--echo +++ Initial status:
SHOW STATUS LIKE 'binlog_gtid_index_%';
--echo +++ GTID Lookup in good index.
--disable_query_log
eval SELECT BINLOG_GTID_POS('$file', $pos) = @gtid_pos AS Gtid_Lookup_Ok;
--enable_query_log
SHOW STATUS LIKE 'binlog_gtid_index_%';
--remove_file $MYSQLD_DATADIR/$file.idx
--echo +++ GTID Lookup, index file is missing.
--disable_query_log
eval SELECT BINLOG_GTID_POS('$file', $pos) = @gtid_pos AS Gtid_Lookup_Ok;
--enable_query_log
SHOW STATUS LIKE 'binlog_gtid_index_%';
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
INSERT INTO t1 VALUES (306);
--let $pos= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid_pos= @@GLOBAL.gtid_binlog_pos;
INSERT INTO t1 VALUES (307);
INSERT INTO t1 VALUES (308);
# Rotate again so we hit an on-disk index file, not the "hot" index.
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
# Corrupt the flag byte of the first page with an unused bit.
--let FILE_TO_CORRUPT= $MYSQLD_DATADIR/$file.idx
--perl
use strict;
use warnings;
use Fcntl qw(:DEFAULT :seek);
sysopen F, $ENV{FILE_TO_CORRUPT}, O_RDWR
or die "Cannot open file $ENV{FILE_TO_CORRUPT}: $!\n";
# Corrupt the flag byte with an unused flag.
sysseek(F, 16, SEEK_SET)
or die "Cannot seek file: $!\n";
my $buf;
sysread(F, $buf, 1)
or die "Cannot read file: $!\n";
$buf= chr(ord($buf) | 0x80);
sysseek(F, 16, SEEK_SET)
or die "Cannot seek file: $!\n";
syswrite(F, $buf, 1) == 1
or die "Cannot write file: $!\n";
close F;
EOF
--echo +++ GTID Lookup, first page of index is corrupt.
--disable_query_log
eval SELECT BINLOG_GTID_POS('$file', $pos) = @gtid_pos AS Gtid_Lookup_Ok;
--enable_query_log
SHOW STATUS LIKE 'binlog_gtid_index_%';
# Corrupt the last byte of the root page.
# Set a small page-size so we test corruption in something not the header page.
SET @old_page_size= @@GLOBAL.binlog_gtid_index_page_size;
SET @old_span_min= @@GLOBAL.binlog_gtid_index_span_min;
SET GLOBAL binlog_gtid_index_page_size= 64;
SET GLOBAL binlog_gtid_index_span_min= 1;
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
INSERT INTO t1 VALUES (310);
INSERT INTO t1 VALUES (311);
INSERT INTO t1 VALUES (312);
--let $pos= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid_pos= @@GLOBAL.gtid_binlog_pos;
INSERT INTO t1 VALUES (313);
INSERT INTO t1 VALUES (314);
INSERT INTO t1 VALUES (315);
INSERT INTO t1 VALUES (316);
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
SET GLOBAL binlog_gtid_index_page_size= @old_page_size;
SET GLOBAL binlog_gtid_index_span_min= @old_span_min;
--let FILE_TO_CORRUPT= $MYSQLD_DATADIR/$file.idx
--perl
use strict;
use warnings;
use Fcntl qw(:DEFAULT :seek);
sysopen F, $ENV{FILE_TO_CORRUPT}, O_RDWR
or die "Cannot open file $ENV{FILE_TO_CORRUPT}: $!\n";
# Tricky: The index is written asynchroneously, it may still be incomplete.
# So wait for the file to be written completely with a root node at the end.
my $count= 0;
for (;;) {
my $end= sysseek(F, 0, SEEK_END);
if ($end > 0 && ($end % 64) == 0) {
# The index file is non-empty with a full page at the end, test if the
# root page has been fully written. This is seen as bit 2 (PAGE_FLAG_LAST)
# and bit 3 (PAGE_FLAG_ROOT) being set (0xc).
my $flag;
if (sysseek(F, -64, SEEK_CUR) &&
sysread(F, $flag, 1) &&
(ord($flag) & 0xc) == 0xc) {
last;
}
}
die "Timeout waiting for GTID index to be non-empty\n"
if ++$count >= 500;
# Simple way to do sub-second sleep.
select(undef, undef, undef, 0.050);
}
# Corrupt the flag byte with an unused flag.
sysseek(F, -2, SEEK_END)
or die "Cannot seek file: $!\n";
my $buf;
sysread(F, $buf, 1)
or die "Cannot read file: $!\n";
$buf= chr(ord($buf) ^ 0x4);
sysseek(F, -2, SEEK_END)
or die "Cannot seek file: $!\n";
syswrite(F, $buf, 1) == 1
or die "Cannot write file: $!\n";
close F;
EOF
--echo +++ GTID Lookup, root page of index is corrupt.
--disable_query_log
eval SELECT BINLOG_GTID_POS('$file', $pos) = @gtid_pos AS Gtid_Lookup_Ok;
--enable_query_log
SHOW STATUS LIKE 'binlog_gtid_index_%';
--echo *** Test BINLOG_GTID_POS() with too-large offset.
# New binlog to skip the now corrupted one.
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
INSERT INTO t1 VALUES (401);
INSERT INTO t1 VALUES (402);
--echo +++ Test the hot index.
--replace_result $file FILE
eval SELECT BINLOG_GTID_POS('$file', 100000000);
SHOW STATUS LIKE 'binlog_gtid_index_%';
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
--echo +++ Test the cold index.
--replace_result $file FILE
eval SELECT BINLOG_GTID_POS('$file', 100000000);
SHOW STATUS LIKE 'binlog_gtid_index_%';
--enable_ps2_protocol
DROP TABLE t1;
|