Skip to content

Commit 8451e09

Browse files
committed
MDEV-11556 InnoDB redo log apply fails to adjust data file sizes
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.
1 parent f493e39 commit 8451e09

File tree

16 files changed

+1000
-795
lines changed

16 files changed

+1000
-795
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
SET GLOBAL innodb_file_per_table=0;
2+
SET GLOBAL innodb_file_format=barracuda;
3+
CREATE TABLE t(a INT)ENGINE=InnoDB;
4+
SET GLOBAL innodb_file_per_table=1;
5+
CREATE TABLE ibd4(a INT UNIQUE)ENGINE=InnoDB;
6+
CREATE TABLE ibd4f(a INT UNIQUE)ENGINE=InnoDB;
7+
CREATE TABLE ibd5(a INT UNIQUE, b INT UNIQUE)ENGINE=InnoDB;
8+
# Kill the server
9+
DROP TABLE t,ibd4,ibd4f,ibd5;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--loose-innodb-sys-indexes
2+
--innodb-data-file-path=ibdata1:1M:autoextend
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
--source include/have_innodb.inc
2+
--source include/not_embedded.inc
3+
4+
let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
5+
let MYSQLD_DATADIR=`select @@datadir`;
6+
let MYSQLD_IS_DEBUG=`select version() like '%debug%'`;
7+
--source include/no_checkpoint_start.inc
8+
SET GLOBAL innodb_file_per_table=0;
9+
SET GLOBAL innodb_file_format=barracuda;
10+
CREATE TABLE t(a INT)ENGINE=InnoDB;
11+
let INNODB_ROOT_PAGE= `SELECT page_no FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE name='GEN_CLUST_INDEX'`;
12+
SET GLOBAL innodb_file_per_table=1;
13+
14+
CREATE TABLE ibd4(a INT UNIQUE)ENGINE=InnoDB;
15+
CREATE TABLE ibd4f(a INT UNIQUE)ENGINE=InnoDB;
16+
CREATE TABLE ibd5(a INT UNIQUE, b INT UNIQUE)ENGINE=InnoDB;
17+
18+
let $drop_tables= DROP TABLE t,ibd4,ibd4f,ibd5;
19+
--let CLEANUP_IF_CHECKPOINT= $drop_tables;
20+
--source ../include/no_checkpoint_end.inc
21+
22+
perl;
23+
use Fcntl 'SEEK_CUR', 'SEEK_END';
24+
25+
my $page_size = $ENV{'INNODB_PAGE_SIZE'};
26+
my $restart = 'restart';
27+
if ($ENV{'MYSQLD_IS_DEBUG'})
28+
{
29+
# It is impractical to ensure that CREATE TABLE t will extend ibdata1.
30+
# We rely on innodb_system_tablespace_extend_debug=1
31+
# to recover from this fault injection if no size change was redo-logged.
32+
my $root = $ENV{'INNODB_ROOT_PAGE'};
33+
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}ibdata1") or die;
34+
my $size = sysseek(FILE, 0, SEEK_END) / $page_size;
35+
seek(FILE, $page_size * ($root + 1), SEEK_SET) or die;
36+
my $empty_tail= 1;
37+
while(<FILE>) { unless (/\0*/gso) { $empty_tail= 0; last } }
38+
if ($empty_tail)
39+
{
40+
$restart = 'restart: --innodb-data-file-size-debug=' . $size;
41+
truncate(FILE, $page_size * $root);
42+
}
43+
close FILE;
44+
}
45+
open(FILE, ">$ENV{MYSQLTEST_VARDIR}/log/start_mysqld.txt") || die;
46+
print FILE '--exec echo "', $restart, '" > $_expect_file_name
47+
--enable_reconnect
48+
--source include/wait_until_connected_again.inc
49+
--disable_reconnect
50+
';
51+
close FILE;
52+
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}test/ibd4.ibd") or die;
53+
truncate(FILE, $page_size * 4);
54+
close FILE;
55+
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}test/ibd4f.ibd") or die;
56+
truncate(FILE, $page_size * 4 + 1234);
57+
close FILE;
58+
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}test/ibd5.ibd") or die;
59+
truncate(FILE, $page_size * 5);
60+
close FILE;
61+
EOF
62+
63+
--source $MYSQLTEST_VARDIR/log/start_mysqld.txt
64+
--remove_file $MYSQLTEST_VARDIR/log/start_mysqld.txt
65+
66+
eval $drop_tables;

mysql-test/suite/sys_vars/r/sysvars_innodb.result

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,20 @@ NUMERIC_BLOCK_SIZE NULL
579579
ENUM_VALUE_LIST NULL
580580
READ_ONLY YES
581581
COMMAND_LINE_ARGUMENT REQUIRED
582+
VARIABLE_NAME INNODB_DATA_FILE_SIZE_DEBUG
583+
SESSION_VALUE NULL
584+
GLOBAL_VALUE 0
585+
GLOBAL_VALUE_ORIGIN COMPILE-TIME
586+
DEFAULT_VALUE 0
587+
VARIABLE_SCOPE GLOBAL
588+
VARIABLE_TYPE BIGINT UNSIGNED
589+
VARIABLE_COMMENT InnoDB system tablespace size to be set in recovery.
590+
NUMERIC_MIN_VALUE 0
591+
NUMERIC_MAX_VALUE 4294967295
592+
NUMERIC_BLOCK_SIZE 0
593+
ENUM_VALUE_LIST NULL
594+
READ_ONLY YES
595+
COMMAND_LINE_ARGUMENT REQUIRED
582596
VARIABLE_NAME INNODB_DATA_HOME_DIR
583597
SESSION_VALUE NULL
584598
GLOBAL_VALUE

0 commit comments

Comments
 (0)