Skip to content

Commit

Permalink
MDEV-11556 InnoDB redo log apply fails to adjust data file sizes
Browse files Browse the repository at this point in the history
fil_space_t::recv_size: New member: recovered tablespace size in pages;
0 if no size change was read from the redo log,
or if the size change was implemented.

fil_space_set_recv_size(): New function for setting space->recv_size.

innodb_data_file_size_debug: A debug parameter for setting the system
tablespace size in recovery even when the redo log does not contain
any size changes. It is hard to write a small test case that would
cause the system tablespace to be extended at the critical moment.

recv_parse_log_rec(): Note those tablespaces whose size is being changed
by the redo log, by invoking fil_space_set_recv_size().

innobase_init(): Correct an error message, and do not require a larger
innodb_buffer_pool_size when starting up with a smaller innodb_page_size.

innobase_start_or_create_for_mysql(): Allow startup with any initial
size of the ibdata1 file if the autoextend attribute is set. Require
the minimum size of fixed-size system tablespaces to be 640 pages,
not 10 megabytes. Implement innodb_data_file_size_debug.

open_or_create_data_files(): Round the system tablespace size down
to pages, not to full megabytes, (Our test truncates the system
tablespace to more than 800 pages with innodb_page_size=4k.
InnoDB should not imagine that it was truncated to 768 pages
and then overwrite good pages in the tablespace.)

fil_flush_low(): Refactored from fil_flush().

fil_space_extend_must_retry(): Refactored from
fil_extend_space_to_desired_size().

fil_mutex_enter_and_prepare_for_io(): Extend the tablespace if
fil_space_set_recv_size() was called.

The test case has been successfully run with all the
innodb_page_size values 4k, 8k, 16k, 32k, 64k.
  • Loading branch information
dr-m committed Dec 30, 2016
1 parent f493e39 commit 8451e09
Show file tree
Hide file tree
Showing 16 changed files with 1,000 additions and 795 deletions.
9 changes: 9 additions & 0 deletions mysql-test/suite/innodb/r/log_data_file_size.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
SET GLOBAL innodb_file_per_table=0;
SET GLOBAL innodb_file_format=barracuda;
CREATE TABLE t(a INT)ENGINE=InnoDB;
SET GLOBAL innodb_file_per_table=1;
CREATE TABLE ibd4(a INT UNIQUE)ENGINE=InnoDB;
CREATE TABLE ibd4f(a INT UNIQUE)ENGINE=InnoDB;
CREATE TABLE ibd5(a INT UNIQUE, b INT UNIQUE)ENGINE=InnoDB;
# Kill the server
DROP TABLE t,ibd4,ibd4f,ibd5;
2 changes: 2 additions & 0 deletions mysql-test/suite/innodb/t/log_data_file_size.opt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--loose-innodb-sys-indexes
--innodb-data-file-path=ibdata1:1M:autoextend
66 changes: 66 additions & 0 deletions mysql-test/suite/innodb/t/log_data_file_size.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
--source include/have_innodb.inc
--source include/not_embedded.inc

let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
let MYSQLD_DATADIR=`select @@datadir`;
let MYSQLD_IS_DEBUG=`select version() like '%debug%'`;
--source include/no_checkpoint_start.inc
SET GLOBAL innodb_file_per_table=0;
SET GLOBAL innodb_file_format=barracuda;
CREATE TABLE t(a INT)ENGINE=InnoDB;
let INNODB_ROOT_PAGE= `SELECT page_no FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE name='GEN_CLUST_INDEX'`;
SET GLOBAL innodb_file_per_table=1;

CREATE TABLE ibd4(a INT UNIQUE)ENGINE=InnoDB;
CREATE TABLE ibd4f(a INT UNIQUE)ENGINE=InnoDB;
CREATE TABLE ibd5(a INT UNIQUE, b INT UNIQUE)ENGINE=InnoDB;

let $drop_tables= DROP TABLE t,ibd4,ibd4f,ibd5;
--let CLEANUP_IF_CHECKPOINT= $drop_tables;
--source ../include/no_checkpoint_end.inc

perl;
use Fcntl 'SEEK_CUR', 'SEEK_END';

my $page_size = $ENV{'INNODB_PAGE_SIZE'};
my $restart = 'restart';
if ($ENV{'MYSQLD_IS_DEBUG'})
{
# It is impractical to ensure that CREATE TABLE t will extend ibdata1.
# We rely on innodb_system_tablespace_extend_debug=1
# to recover from this fault injection if no size change was redo-logged.
my $root = $ENV{'INNODB_ROOT_PAGE'};
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}ibdata1") or die;
my $size = sysseek(FILE, 0, SEEK_END) / $page_size;
seek(FILE, $page_size * ($root + 1), SEEK_SET) or die;
my $empty_tail= 1;
while(<FILE>) { unless (/\0*/gso) { $empty_tail= 0; last } }
if ($empty_tail)
{
$restart = 'restart: --innodb-data-file-size-debug=' . $size;
truncate(FILE, $page_size * $root);
}
close FILE;
}
open(FILE, ">$ENV{MYSQLTEST_VARDIR}/log/start_mysqld.txt") || die;
print FILE '--exec echo "', $restart, '" > $_expect_file_name
--enable_reconnect
--source include/wait_until_connected_again.inc
--disable_reconnect
';
close FILE;
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}test/ibd4.ibd") or die;
truncate(FILE, $page_size * 4);
close FILE;
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}test/ibd4f.ibd") or die;
truncate(FILE, $page_size * 4 + 1234);
close FILE;
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}test/ibd5.ibd") or die;
truncate(FILE, $page_size * 5);
close FILE;
EOF

--source $MYSQLTEST_VARDIR/log/start_mysqld.txt
--remove_file $MYSQLTEST_VARDIR/log/start_mysqld.txt

eval $drop_tables;
14 changes: 14 additions & 0 deletions mysql-test/suite/sys_vars/r/sysvars_innodb.result
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,20 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME INNODB_DATA_FILE_SIZE_DEBUG
SESSION_VALUE NULL
GLOBAL_VALUE 0
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT InnoDB system tablespace size to be set in recovery.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
NUMERIC_BLOCK_SIZE 0
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME INNODB_DATA_HOME_DIR
SESSION_VALUE NULL
GLOBAL_VALUE
Expand Down
Loading

0 comments on commit 8451e09

Please sign in to comment.