2016-12-20 15:03:56 +02:00
|
|
|
--echo #
|
|
|
|
--echo # Bug #17335427 INNODB CAN NOT USE THE DOUBLEWRITE BUFFER PROPERLY
|
|
|
|
--echo # Bug #18144349 INNODB CANNOT USE THE DOUBLEWRITE BUFFER FOR THE FIRST
|
|
|
|
--echo # PAGE OF SYSTEM TABLESPACE
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
--source include/have_innodb.inc
|
|
|
|
--source include/have_debug.inc
|
|
|
|
--source include/not_embedded.inc
|
|
|
|
|
|
|
|
# Slow shutdown and restart to make sure ibuf merge is finished
|
|
|
|
SET GLOBAL innodb_fast_shutdown = 0;
|
|
|
|
--source include/restart_mysqld.inc
|
|
|
|
|
|
|
|
--disable_query_log
|
2016-12-29 15:03:12 +02:00
|
|
|
call mtr.add_suppression("space header page consists of zero bytes.*test.t1");
|
|
|
|
call mtr.add_suppression("checksum mismatch in tablespace.*test.t1");
|
|
|
|
call mtr.add_suppression("Current page size .* != page size on page");
|
|
|
|
call mtr.add_suppression("innodb-page-size mismatch in tablespace.*test.t1");
|
2016-12-20 15:03:56 +02:00
|
|
|
call mtr.add_suppression("Database page corruption");
|
|
|
|
--enable_query_log
|
|
|
|
|
|
|
|
let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
|
|
|
|
let MYSQLD_DATADIR=`select @@datadir`;
|
|
|
|
|
|
|
|
show variables like 'innodb_doublewrite';
|
|
|
|
show variables like 'innodb_fil_make_page_dirty_debug';
|
|
|
|
show variables like 'innodb_saved_page_number_debug';
|
|
|
|
|
|
|
|
create table t1 (f1 int primary key, f2 blob) 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;
|
|
|
|
|
|
|
|
--echo # ---------------------------------------------------------------
|
|
|
|
--echo # Test Begin: Test if recovery works if first page of user
|
|
|
|
--echo # tablespace is full of zeroes.
|
|
|
|
|
|
|
|
select space from information_schema.innodb_sys_tables
|
|
|
|
where name = 'test/t1' into @space_id;
|
|
|
|
|
|
|
|
--echo # Ensure that dirty pages of table t1 is flushed.
|
|
|
|
flush tables t1 for export;
|
|
|
|
unlock tables;
|
|
|
|
|
|
|
|
begin;
|
|
|
|
insert into t1 values (6, repeat('%', 12));
|
|
|
|
|
|
|
|
--source ../include/no_checkpoint_start.inc
|
|
|
|
|
|
|
|
--echo # Make the first page dirty for table t1
|
|
|
|
set global innodb_saved_page_number_debug = 0;
|
|
|
|
set global innodb_fil_make_page_dirty_debug = @space_id;
|
|
|
|
|
|
|
|
--echo # Ensure that dirty pages of table t1 are flushed.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--let CLEANUP_IF_CHECKPOINT=drop table t1;
|
|
|
|
--source ../include/no_checkpoint_end.inc
|
|
|
|
|
|
|
|
--echo # Make the first page (page_no=0) of the user tablespace
|
|
|
|
--echo # full of zeroes.
|
|
|
|
perl;
|
|
|
|
use IO::Handle;
|
|
|
|
my $fname= "$ENV{'MYSQLD_DATADIR'}test/t1.ibd";
|
|
|
|
open(FILE, "+<", $fname) or die;
|
|
|
|
FILE->autoflush(1);
|
|
|
|
binmode FILE;
|
|
|
|
print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'});
|
|
|
|
close FILE;
|
|
|
|
EOF
|
|
|
|
|
|
|
|
--source include/start_mysqld.inc
|
|
|
|
|
|
|
|
check table t1;
|
|
|
|
select f1, f2 from t1;
|
|
|
|
|
|
|
|
--echo # Test End
|
|
|
|
--echo # ---------------------------------------------------------------
|
|
|
|
--echo # Test Begin: Test if recovery works if first page of user
|
|
|
|
--echo # tablespace is corrupted.
|
|
|
|
|
|
|
|
select space from information_schema.innodb_sys_tables
|
|
|
|
where name = 'test/t1' into @space_id;
|
|
|
|
|
|
|
|
--echo # Ensure that dirty pages of table t1 is flushed.
|
|
|
|
flush tables t1 for export;
|
|
|
|
unlock tables;
|
|
|
|
|
|
|
|
begin;
|
|
|
|
insert into t1 values (6, repeat('%', 12));
|
|
|
|
|
|
|
|
--source ../include/no_checkpoint_start.inc
|
|
|
|
|
|
|
|
--echo # Make the first page dirty for table t1
|
|
|
|
set global innodb_saved_page_number_debug = 0;
|
|
|
|
set global innodb_fil_make_page_dirty_debug = @space_id;
|
|
|
|
|
|
|
|
--echo # Ensure that dirty pages of table t1 are flushed.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--source include/no_checkpoint_end.inc
|
|
|
|
|
|
|
|
--echo # Corrupt the first page (page_no=0) of the user tablespace.
|
|
|
|
perl;
|
|
|
|
use IO::Handle;
|
|
|
|
my $fname= "$ENV{'MYSQLD_DATADIR'}test/t1.ibd";
|
|
|
|
open(FILE, "+<", $fname) or die;
|
|
|
|
FILE->autoflush(1);
|
|
|
|
binmode FILE;
|
|
|
|
print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}/2);
|
|
|
|
close FILE;
|
|
|
|
EOF
|
|
|
|
|
|
|
|
--source include/start_mysqld.inc
|
|
|
|
|
|
|
|
check table t1;
|
|
|
|
select f1, f2 from t1;
|
|
|
|
|
|
|
|
--echo # Test End
|
|
|
|
--echo # ---------------------------------------------------------------
|
|
|
|
--echo # Test Begin: Test if recovery works if 2nd page of user
|
|
|
|
--echo # tablespace is full of zeroes.
|
|
|
|
|
|
|
|
select space from information_schema.innodb_sys_tables
|
|
|
|
where name = 'test/t1' into @space_id;
|
|
|
|
|
|
|
|
--echo # Ensure that dirty pages of table t1 is flushed.
|
|
|
|
flush tables t1 for export;
|
|
|
|
unlock tables;
|
|
|
|
|
|
|
|
begin;
|
|
|
|
insert into t1 values (6, repeat('%', 400));
|
|
|
|
|
|
|
|
--source ../include/no_checkpoint_start.inc
|
|
|
|
|
|
|
|
--echo # Make the 2nd page dirty for table t1
|
|
|
|
set global innodb_saved_page_number_debug = 1;
|
|
|
|
set global innodb_fil_make_page_dirty_debug = @space_id;
|
|
|
|
|
|
|
|
--echo # Ensure that dirty pages of table t1 are flushed.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--source include/no_checkpoint_end.inc
|
|
|
|
|
|
|
|
--echo # Make the 2nd page (page_no=1) of the tablespace all zeroes.
|
|
|
|
perl;
|
|
|
|
use IO::Handle;
|
|
|
|
my $fname= "$ENV{'MYSQLD_DATADIR'}test/t1.ibd";
|
|
|
|
open(FILE, "+<", $fname) or die;
|
|
|
|
FILE->autoflush(1);
|
|
|
|
binmode FILE;
|
|
|
|
seek(FILE, $ENV{'INNODB_PAGE_SIZE'}, SEEK_SET);
|
|
|
|
print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'});
|
|
|
|
close FILE;
|
|
|
|
EOF
|
|
|
|
|
|
|
|
--source include/start_mysqld.inc
|
|
|
|
|
|
|
|
check table t1;
|
|
|
|
select f1, f2 from t1;
|
|
|
|
|
|
|
|
--echo # Test End
|
|
|
|
--echo # ---------------------------------------------------------------
|
|
|
|
--echo # Test Begin: Test if recovery works if 2nd page of user
|
|
|
|
--echo # tablespace is corrupted.
|
|
|
|
|
|
|
|
select space from information_schema.innodb_sys_tables
|
|
|
|
where name = 'test/t1' into @space_id;
|
|
|
|
|
|
|
|
--echo # Ensure that dirty pages of table t1 is flushed.
|
|
|
|
flush tables t1 for export;
|
|
|
|
unlock tables;
|
|
|
|
|
|
|
|
begin;
|
|
|
|
insert into t1 values (6, repeat('%', 400));
|
|
|
|
|
|
|
|
--source ../include/no_checkpoint_start.inc
|
|
|
|
|
|
|
|
--echo # Make the 2nd page dirty for table t1
|
|
|
|
set global innodb_saved_page_number_debug = 1;
|
|
|
|
set global innodb_fil_make_page_dirty_debug = @space_id;
|
|
|
|
|
|
|
|
--echo # Ensure that the dirty pages of table t1 are flushed.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--source include/no_checkpoint_end.inc
|
|
|
|
|
|
|
|
--echo # Corrupt the 2nd page (page_no=1) of the user tablespace.
|
|
|
|
perl;
|
|
|
|
use IO::Handle;
|
|
|
|
my $fname= "$ENV{'MYSQLD_DATADIR'}test/t1.ibd";
|
|
|
|
open(FILE, "+<", $fname) or die;
|
|
|
|
FILE->autoflush(1);
|
|
|
|
binmode FILE;
|
|
|
|
seek(FILE, $ENV{'INNODB_PAGE_SIZE'}, SEEK_SET);
|
|
|
|
print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}/2);
|
|
|
|
close FILE;
|
|
|
|
EOF
|
|
|
|
|
|
|
|
--source include/start_mysqld.inc
|
|
|
|
|
|
|
|
check table t1;
|
|
|
|
select f1, f2 from t1;
|
|
|
|
|
|
|
|
--echo # Test End
|
|
|
|
--echo # ---------------------------------------------------------------
|
|
|
|
--echo # Test Begin: Test if recovery works if first page of
|
|
|
|
--echo # system tablespace is full of zeroes.
|
|
|
|
|
|
|
|
begin;
|
|
|
|
insert into t1 values (6, repeat('%', 400));
|
|
|
|
|
|
|
|
--echo # Ensure that all dirty pages in the system are flushed.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--echo # Make the first page dirty for system tablespace
|
|
|
|
set global innodb_saved_page_number_debug = 0;
|
|
|
|
set global innodb_fil_make_page_dirty_debug = 0;
|
|
|
|
|
|
|
|
--echo # Ensure that the dirty page of system tablespace is also flushed.
|
|
|
|
# We do this after the transaction starts and all dirty pages have been flushed
|
|
|
|
# already. So flushing of this specified dirty page will surely keep the
|
|
|
|
# copy in doublewrite buffer, and no more writes to doublewrite buffer would
|
|
|
|
# overwrite the copy. Thus, we can safely modify the original page when server
|
|
|
|
# is down. So do the following testings.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--source include/kill_mysqld.inc
|
|
|
|
|
|
|
|
--echo # Make the first page (page_no=0) of the system tablespace
|
|
|
|
--echo # all zeroes.
|
|
|
|
perl;
|
|
|
|
use IO::Handle;
|
|
|
|
my $fname= "$ENV{'MYSQLD_DATADIR'}ibdata1";
|
|
|
|
open(FILE, "+<", $fname) or die;
|
|
|
|
FILE->autoflush(1);
|
|
|
|
binmode FILE;
|
|
|
|
print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'});
|
|
|
|
close FILE;
|
|
|
|
EOF
|
|
|
|
|
|
|
|
--source include/start_mysqld.inc
|
|
|
|
|
|
|
|
check table t1;
|
|
|
|
select f1, f2 from t1;
|
|
|
|
|
|
|
|
--echo # Test End
|
|
|
|
--echo # ---------------------------------------------------------------
|
|
|
|
--echo # Test Begin: Test if recovery works if first page of
|
|
|
|
--echo # system tablespace is corrupted.
|
|
|
|
|
|
|
|
begin;
|
|
|
|
insert into t1 values (6, repeat('%', 400));
|
|
|
|
|
|
|
|
--echo # Ensure that all dirty pages in the system are flushed.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--echo # Make the first page dirty for system tablespace
|
|
|
|
set global innodb_saved_page_number_debug = 0;
|
|
|
|
set global innodb_fil_make_page_dirty_debug = 0;
|
|
|
|
|
|
|
|
--echo # Ensure that the dirty page of system tablespace is also flushed.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--source include/kill_mysqld.inc
|
|
|
|
|
|
|
|
--echo # Corrupt the first page (page_no=0) of the system tablespace.
|
|
|
|
perl;
|
|
|
|
use IO::Handle;
|
|
|
|
my $fname= "$ENV{'MYSQLD_DATADIR'}ibdata1";
|
|
|
|
open(FILE, "+<", $fname) or die;
|
|
|
|
FILE->autoflush(1);
|
|
|
|
binmode FILE;
|
|
|
|
print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}/2);
|
|
|
|
close FILE;
|
|
|
|
EOF
|
|
|
|
|
|
|
|
--source include/start_mysqld.inc
|
|
|
|
|
|
|
|
check table t1;
|
|
|
|
select f1, f2 from t1;
|
|
|
|
|
|
|
|
--echo # Test End
|
|
|
|
--echo # ---------------------------------------------------------------
|
|
|
|
--echo # Test Begin: Test if recovery works if 2nd page of
|
|
|
|
--echo # system tablespace is full of zeroes.
|
|
|
|
|
|
|
|
begin;
|
|
|
|
insert into t1 values (6, repeat('%', 400));
|
|
|
|
|
|
|
|
--echo # Ensure that all dirty pages in the system are flushed.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--echo # Make the second page dirty for system tablespace
|
|
|
|
set global innodb_saved_page_number_debug = 1;
|
|
|
|
set global innodb_fil_make_page_dirty_debug = 0;
|
|
|
|
|
|
|
|
--echo # Ensure that the dirty page of system tablespace is also flushed.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--source include/kill_mysqld.inc
|
|
|
|
|
|
|
|
--echo # Make the 2nd page (page_no=1) of the system tablespace
|
|
|
|
--echo # all zeroes.
|
|
|
|
perl;
|
|
|
|
use IO::Handle;
|
|
|
|
my $fname= "$ENV{'MYSQLD_DATADIR'}ibdata1";
|
|
|
|
open(FILE, "+<", $fname) or die;
|
|
|
|
FILE->autoflush(1);
|
|
|
|
binmode FILE;
|
|
|
|
seek(FILE, $ENV{'INNODB_PAGE_SIZE'}, SEEK_SET);
|
|
|
|
print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'});
|
|
|
|
close FILE;
|
|
|
|
EOF
|
|
|
|
|
|
|
|
--source include/start_mysqld.inc
|
|
|
|
|
|
|
|
check table t1;
|
|
|
|
select f1, f2 from t1;
|
|
|
|
|
|
|
|
--echo # Test End
|
|
|
|
--echo # ---------------------------------------------------------------
|
|
|
|
--echo # Test Begin: Test if recovery works if 2nd page of
|
|
|
|
--echo # system tablespace is corrupted.
|
|
|
|
|
|
|
|
begin;
|
|
|
|
insert into t1 values (6, repeat('%', 400));
|
|
|
|
|
|
|
|
--echo # Ensure that all dirty pages in the system are flushed.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--echo # Make the second page dirty for system tablespace
|
|
|
|
set global innodb_saved_page_number_debug = 1;
|
|
|
|
set global innodb_fil_make_page_dirty_debug = 0;
|
|
|
|
|
|
|
|
--echo # Ensure that the dirty page of system tablespace is also flushed.
|
|
|
|
set global innodb_buf_flush_list_now = 1;
|
|
|
|
|
|
|
|
--source include/kill_mysqld.inc
|
|
|
|
|
|
|
|
--echo # Make the 2nd page (page_no=1) of the system tablespace
|
|
|
|
--echo # all zeroes.
|
|
|
|
perl;
|
|
|
|
use IO::Handle;
|
|
|
|
my $fname= "$ENV{'MYSQLD_DATADIR'}ibdata1";
|
|
|
|
open(FILE, "+<", $fname) or die;
|
|
|
|
FILE->autoflush(1);
|
|
|
|
binmode FILE;
|
|
|
|
seek(FILE, $ENV{'INNODB_PAGE_SIZE'}, SEEK_SET);
|
|
|
|
print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}/2);
|
|
|
|
close FILE;
|
|
|
|
EOF
|
|
|
|
|
|
|
|
--source include/start_mysqld.inc
|
|
|
|
|
|
|
|
check table t1;
|
|
|
|
select f1, f2 from t1;
|
|
|
|
|
|
|
|
--echo # Test End
|
|
|
|
--echo # ---------------------------------------------------------------
|
|
|
|
|
|
|
|
drop table t1;
|