mirror of
https://github.com/MariaDB/server.git
synced 2025-08-09 22:24:09 +03:00
- InnoDB fails to find the space id from the page0 of the tablespace. In that case, InnoDB can use doublewrite buffer to recover the page0 and write into the file. - buf_dblwr_t::init_or_load_pages(): Loads only the pages which are valid.(page lsn >= checkpoint). To do that, InnoDB has to open the redo log before system tablespace, read the latest checkpoint information. recv_dblwr_t::find_first_page(): 1) Iterate the doublewrite buffer pages and find the 0th page 2) Read the tablespace flags, space id from the 0th page. 3) Read the 1st, 2nd and 3rd page from tablespace file and compare the space id with the space id which is stored in doublewrite buffer. 4) If it matches then we can write into the file. 5) Return space which matches the pages from the file. SysTablespace::read_lsn_and_check_flags(): Remove the retry logic for validating the first page. After restoring the first page from doublewrite buffer, assign tablespace flags by reading the first page. recv_recovery_read_max_checkpoint(): Reads the maximum checkpoint information from log file recv_recovery_from_checkpoint_start(): Avoid reading the checkpoint header information from log file Datafile::validate_first_page(): Throw error in case of first page validation fails.
155 lines
5.5 KiB
Plaintext
155 lines
5.5 KiB
Plaintext
|
|
--echo #
|
|
--echo # MDEV-32242 innodb.doublewrite test case always is skipped
|
|
--echo #
|
|
|
|
--source include/innodb_page_size.inc
|
|
--source include/not_embedded.inc
|
|
|
|
--disable_query_log
|
|
call mtr.add_suppression("InnoDB: Data file .* uses page size .* but the innodb_page_size start-up parameter is");
|
|
call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS");
|
|
call mtr.add_suppression("InnoDB: New log files created");
|
|
call mtr.add_suppression("InnoDB: Cannot create doublewrite buffer: the first file in innodb_data_file_path must be at least (3|6|12)M\\.");
|
|
call mtr.add_suppression("InnoDB: Database creation was aborted");
|
|
call mtr.add_suppression("Plugin 'InnoDB' (init function returned error|registration as a STORAGE ENGINE failed)");
|
|
call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile");
|
|
call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: ");
|
|
call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd");
|
|
call mtr.add_suppression("\\[Warning\\] Found 1 prepared XA transactions");
|
|
call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:");
|
|
--enable_query_log
|
|
|
|
let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
|
|
let MYSQLD_DATADIR=`select @@datadir`;
|
|
let ALGO=`select @@innodb_checksum_algorithm`;
|
|
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
|
|
|
|
create table t1 (f1 int primary key, f2 blob) stats_persistent=0, engine=innodb;
|
|
|
|
start transaction;
|
|
insert into t1 values(1, repeat('#',12));
|
|
insert into t1 values(2, repeat('+',12));
|
|
insert into t1 values(3, repeat('/',12));
|
|
insert into t1 values(4, repeat('-',12));
|
|
insert into t1 values(5, repeat('.',12));
|
|
commit work;
|
|
|
|
# Slow shutdown and restart to make sure ibuf merge is finished
|
|
SET GLOBAL innodb_fast_shutdown = 0;
|
|
let $shutdown_timeout=;
|
|
--source include/restart_mysqld.inc
|
|
--source ../include/no_checkpoint_start.inc
|
|
connect (dml,localhost,root,,);
|
|
XA START 'x';
|
|
insert into t1 values (6, repeat('%', @@innodb_page_size/2));
|
|
XA END 'x';
|
|
XA PREPARE 'x';
|
|
disconnect dml;
|
|
connection default;
|
|
|
|
flush table t1 for export;
|
|
|
|
let $restart_parameters=;
|
|
--let CLEANUP_IF_CHECKPOINT=drop table t1, unexpected_checkpoint;
|
|
--source ../include/no_checkpoint_end.inc
|
|
|
|
perl;
|
|
use IO::Handle;
|
|
do "$ENV{MTR_SUITE_DIR}/include/crc32.pl";
|
|
my $polynomial = 0x82f63b78; # CRC-32C
|
|
my $algo = $ENV{ALGO};
|
|
die "Unsupported innodb_checksum_algorithm=$algo\n" unless $algo =~ /crc32/;
|
|
|
|
my $fname= "$ENV{'MYSQLD_DATADIR'}test/t1.ibd";
|
|
my $page_size = $ENV{INNODB_PAGE_SIZE};
|
|
my $page;
|
|
do "$ENV{MTR_SUITE_DIR}/../innodb/include/crc32.pl";
|
|
open(FILE, "+<", $fname) or die;
|
|
sysseek(FILE, ($page_size/2), 0);
|
|
syswrite(FILE, chr(0) x ($page_size/2));
|
|
sysseek(FILE, 3*$page_size, 0);
|
|
sysread(FILE, $page, $page_size)==$page_size||die "Unable to read $name\n";
|
|
sysseek(FILE, 3*$page_size, 0)||die "Unable to seek $fname\n";
|
|
syswrite(FILE, chr(0) x ($page_size/2));
|
|
close FILE;
|
|
|
|
# Change the flag offset of page 0 in doublewrite buffer
|
|
open(FILE, "+<", "$ENV{MYSQLD_DATADIR}ibdata1")||die "cannot open ibdata1\n";
|
|
sysseek(FILE, 6 * $page_size - 190, 0)||die "Unable to seek ibdata1\n";
|
|
sysread(FILE, $_, 12) == 12||die "Unable to read TRX_SYS\n";
|
|
my($magic,$d1,$d2)=unpack "NNN", $_;
|
|
die "magic=$magic, $d1, $d2\n" unless $magic == 536853855 && $d2 >= $d1 + 64;
|
|
sysseek(FILE, $d1 * $page_size, 0)||die "Unable to seek ibdata1\n";
|
|
# Find the page in the doublewrite buffer
|
|
for (my $d = $d1; $d < $d2 + 64; $d++)
|
|
{
|
|
sysread(FILE, $_, $page_size)==$page_size||die "Cannot read doublewrite\n";
|
|
next unless $_ eq $page;
|
|
sysseek(FILE, $d * $page_size, 0)||die "Unable to seek ibdata1\n";
|
|
# Write buggy FSP_SPACE_FLAGS to the doublewrite buffer for page
|
|
my $badflags = 0x0006FFFF;
|
|
substr ($_, 54, 4) = pack("N", $badflags);
|
|
if ($algo =~ /full_crc32/)
|
|
{
|
|
my $ck = mycrc32(substr($_, 0, $page_size - 4), 0, $polynomial);
|
|
substr($_, $page_size - 4, 4) = pack("N", $ck);
|
|
}
|
|
else
|
|
{
|
|
# Replace the innodb_checksum_algorithm=crc32 checksum
|
|
my $ck= pack("N",
|
|
mycrc32(substr($_, 4, 22), 0, $polynomial) ^
|
|
mycrc32(substr($_, 38, $page_size - 38 - 8), 0,
|
|
$polynomial));
|
|
substr ($_, 0, 4) = $ck;
|
|
substr ($_, $page_size - 8, 4) = $ck;
|
|
}
|
|
syswrite(FILE, $_, $page_size)==$page_size||die;
|
|
close(FILE);
|
|
exit 0;
|
|
}
|
|
die "Did not find the page in the doublewrite buffer ($d1,$d2)\n";
|
|
EOF
|
|
|
|
--source include/start_mysqld.inc
|
|
let SEARCH_PATTERN=InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile;
|
|
--source include/search_pattern_in_file.inc
|
|
let SEARCH_PATTERN=InnoDB: Recovered page \[page id: space=[1-9][0-9]*, page number=3\];
|
|
--source include/search_pattern_in_file.inc
|
|
XA ROLLBACK 'x';
|
|
check table t1;
|
|
select f1, f2 from t1;
|
|
|
|
--source ../include/no_checkpoint_start.inc
|
|
connect (dml,localhost,root,,);
|
|
XA START 'x';
|
|
insert into t1 values (6, repeat('%', @@innodb_page_size/2));
|
|
XA END 'x';
|
|
XA PREPARE 'x';
|
|
disconnect dml;
|
|
connection default;
|
|
|
|
flush table t1 for export;
|
|
|
|
let $restart_parameters=;
|
|
--source ../include/no_checkpoint_end.inc
|
|
|
|
# Zero out the first page in file and try to recover from dblwr
|
|
perl;
|
|
use IO::Handle;
|
|
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}test/t1.ibd") or die;
|
|
syswrite(FILE, chr(0) x $ENV{INNODB_PAGE_SIZE});
|
|
close FILE;
|
|
EOF
|
|
|
|
--source include/start_mysqld.inc
|
|
let SEARCH_PATTERN=InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile;
|
|
--source include/search_pattern_in_file.inc
|
|
XA ROLLBACK 'x';
|
|
check table t1;
|
|
select f1, f2 from t1;
|
|
drop table t1;
|
|
|
|
--echo # End of 10.5 tests
|