Skip to content

Commit 3271da1

Browse files
committed
MDEV-11814 Refuse innodb_read_only startup if crash recovery is needed
recv_scan_log_recs(): Remember if redo log apply is needed, even if starting up in innodb_read_only mode. recv_recovery_from_checkpoint_start_func(): Refuse innodb_read_only startup if redo log apply is needed.
1 parent 8daa87d commit 3271da1

File tree

4 files changed

+228
-6
lines changed

4 files changed

+228
-6
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
2+
BEGIN;
3+
INSERT INTO t1 VALUES (42);
4+
# Kill and restart: --innodb-log-file-size=6M
5+
SELECT * FROM t1;
6+
a
7+
INSERT INTO t1 VALUES (42);
8+
BEGIN;
9+
DELETE FROM t1;
10+
# Kill and restart: --innodb-log-files-in-group=3 --innodb-log-file-size=5M
11+
SELECT * FROM t1;
12+
a
13+
42
14+
INSERT INTO t1 VALUES (123);
15+
BEGIN;
16+
DELETE FROM t1;
17+
# Kill the server
18+
--innodb-force-recovery-crash=1
19+
--innodb-force-recovery-crash=3
20+
--innodb-force-recovery-crash=4
21+
--innodb-force-recovery-crash=5
22+
--innodb-force-recovery-crash=6
23+
--innodb-force-recovery-crash=7
24+
--innodb-force-recovery-crash=8
25+
--innodb-force-recovery-crash=9
26+
--innodb-force-recovery-crash=10
27+
SELECT * FROM t1;
28+
a
29+
42
30+
123
31+
DROP TABLE t1;
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# Test resizing the InnoDB redo log.
2+
3+
--source include/have_innodb.inc
4+
5+
# Embedded server does not support crashing
6+
--source include/not_embedded.inc
7+
# Avoid CrashReporter popup on Mac
8+
--source include/not_crashrep.inc
9+
# innodb-force-recovery-crash needs debug
10+
--source include/have_debug.inc
11+
12+
if (`SELECT @@innodb_log_file_size = 1048576`) {
13+
--skip Test requires innodb_log_file_size>1M.
14+
}
15+
16+
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
17+
BEGIN;
18+
INSERT INTO t1 VALUES (42);
19+
20+
let $restart_parameters = --innodb-log-file-size=6M;
21+
--source include/kill_and_restart_mysqld.inc
22+
23+
SELECT * FROM t1;
24+
25+
INSERT INTO t1 VALUES (42);
26+
BEGIN;
27+
DELETE FROM t1;
28+
29+
let $restart_parameters = --innodb-log-files-in-group=3 --innodb-log-file-size=5M;
30+
--source include/kill_and_restart_mysqld.inc
31+
32+
SELECT * FROM t1;
33+
34+
INSERT INTO t1 VALUES (123);
35+
36+
let MYSQLD_DATADIR= `select @@datadir`;
37+
let SEARCH_ABORT = NOT FOUND;
38+
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err;
39+
# MDEV-11689 FIXME: add --core-file to $args, and remove all ,134 below
40+
let $args=--innodb --unknown-option --loose-console > $SEARCH_FILE 2>&1;
41+
let $crash=$args --innodb-force-recovery-crash;
42+
43+
BEGIN;
44+
DELETE FROM t1;
45+
46+
--source include/kill_mysqld.inc
47+
48+
--error 2
49+
--exec $MYSQLD_CMD $args --innodb-log-group-home-dir=foo\;bar
50+
let SEARCH_PATTERN= syntax error in innodb_log_group_home_dir;
51+
--source include/search_pattern_in_file.inc
52+
--remove_file $SEARCH_FILE
53+
54+
--echo --innodb-force-recovery-crash=1
55+
--error 3,134
56+
--exec $MYSQLD_CMD $crash=1
57+
let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records;
58+
--source include/search_pattern_in_file.inc
59+
--remove_file $SEARCH_FILE
60+
--echo --innodb-force-recovery-crash=3
61+
--error 3,134
62+
--exec $MYSQLD_CMD $crash=3
63+
let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records;
64+
--source include/search_pattern_in_file.inc
65+
--remove_file $SEARCH_FILE
66+
67+
--error 2
68+
--exec $MYSQLD_CMD $args --innodb-read-only
69+
let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery;
70+
--source include/search_pattern_in_file.inc
71+
--remove_file $SEARCH_FILE
72+
73+
--echo --innodb-force-recovery-crash=4
74+
--error 3,134
75+
--exec $MYSQLD_CMD $crash=4
76+
let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records;
77+
--source include/search_pattern_in_file.inc
78+
let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages;
79+
--source include/search_pattern_in_file.inc
80+
--remove_file $SEARCH_FILE
81+
--echo --innodb-force-recovery-crash=5
82+
--error 3,134
83+
--exec $MYSQLD_CMD $crash=5
84+
let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records;
85+
--source include/search_pattern_in_file.inc
86+
let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages;
87+
--source include/search_pattern_in_file.inc
88+
--remove_file $SEARCH_FILE
89+
90+
--error 2
91+
--exec $MYSQLD_CMD $args --innodb-read-only
92+
let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery;
93+
--source include/search_pattern_in_file.inc
94+
--remove_file $SEARCH_FILE
95+
96+
--echo --innodb-force-recovery-crash=6
97+
--error 3,134
98+
--exec $MYSQLD_CMD $crash=6
99+
let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records;
100+
--source include/search_pattern_in_file.inc
101+
let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages;
102+
--source include/search_pattern_in_file.inc
103+
--remove_file $SEARCH_FILE
104+
--echo --innodb-force-recovery-crash=7
105+
--error 3,134
106+
--exec $MYSQLD_CMD $crash=7
107+
# this crashes right after deleting all log files
108+
--remove_file $SEARCH_FILE
109+
110+
--error 2
111+
--exec $MYSQLD_CMD $args --innodb-read-only
112+
let SEARCH_PATTERN= InnoDB: Cannot create log files in read-only mode;
113+
--source include/search_pattern_in_file.inc
114+
--remove_file $SEARCH_FILE
115+
116+
--echo --innodb-force-recovery-crash=8
117+
--error 3,134
118+
--exec $MYSQLD_CMD $crash=8
119+
let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to;
120+
--source include/search_pattern_in_file.inc
121+
--remove_file $SEARCH_FILE
122+
--echo --innodb-force-recovery-crash=9
123+
--error 3,134
124+
--exec $MYSQLD_CMD $crash=9
125+
let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to;
126+
--source include/search_pattern_in_file.inc
127+
--remove_file $SEARCH_FILE
128+
129+
# We should have perfectly synced files here.
130+
# Rename the log files, and trigger an error in recovery.
131+
--move_file $MYSQLD_DATADIR/ib_logfile101 $MYSQLD_DATADIR/ib_logfile0
132+
--move_file $MYSQLD_DATADIR/ib_logfile1 $MYSQLD_DATADIR/ib_logfile1_hidden
133+
--error 2,134
134+
--exec $MYSQLD_CMD $args
135+
let SEARCH_PATTERN= InnoDB: Only one log file found;
136+
--source include/search_pattern_in_file.inc
137+
--remove_file $SEARCH_FILE
138+
--move_file $MYSQLD_DATADIR/ib_logfile0 $MYSQLD_DATADIR/ib_logfile101
139+
140+
perl;
141+
die unless open(FILE, ">$ENV{MYSQLD_DATADIR}/ib_logfile0");
142+
print FILE "garbage";
143+
close(FILE);
144+
EOF
145+
--error 2,134
146+
--exec $MYSQLD_CMD $args
147+
let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile0 size 7 is not a multiple of innodb_page_size;
148+
--source include/search_pattern_in_file.inc
149+
--remove_file $SEARCH_FILE
150+
--remove_file $MYSQLD_DATADIR/ib_logfile0
151+
--move_file $MYSQLD_DATADIR/ib_logfile101 $MYSQLD_DATADIR/ib_logfile0
152+
153+
perl;
154+
die unless open(FILE, ">$ENV{MYSQLD_DATADIR}/ib_logfile1");
155+
print FILE "junkfill" x 131072;
156+
close(FILE);
157+
EOF
158+
159+
--error 2,134
160+
--exec $MYSQLD_CMD $args
161+
let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile1 is of different size 1048576 bytes than other log files;
162+
--source include/search_pattern_in_file.inc
163+
--remove_file $SEARCH_FILE
164+
--remove_file $MYSQLD_DATADIR/ib_logfile1
165+
--move_file $MYSQLD_DATADIR/ib_logfile0 $MYSQLD_DATADIR/ib_logfile101
166+
--move_file $MYSQLD_DATADIR/ib_logfile1_hidden $MYSQLD_DATADIR/ib_logfile1
167+
168+
--echo --innodb-force-recovery-crash=10
169+
--error 3,134
170+
--exec $MYSQLD_CMD $crash=10
171+
let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to;
172+
--source include/search_pattern_in_file.inc
173+
let SEARCH_PATTERN= InnoDB: Renaming log file .*ib_logfile101 to .*ib_logfile0;
174+
--source include/search_pattern_in_file.inc
175+
--remove_file $SEARCH_FILE
176+
177+
--let $restart_parameters=
178+
--source include/start_mysqld.inc
179+
180+
--disable_query_log
181+
call mtr.add_suppression("InnoDB: Resizing redo log");
182+
call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files");
183+
call mtr.add_suppression("InnoDB: New log files created");
184+
call mtr.add_suppression("InnoDB: The log sequence numbers [0-9]+ and [0-9]+ in ibdata files do not match the log sequence number [0-9]+ in the ib_logfiles");
185+
--enable_query_log
186+
187+
SELECT * FROM t1;
188+
DROP TABLE t1;

storage/innobase/include/srv0start.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ struct dict_table_t;
4242
fprintf(stderr, "innodb_force_recovery_crash=%lu\n", \
4343
srv_force_recovery_crash); \
4444
fflush(stderr); \
45-
abort(); \
45+
exit(3); \
4646
} \
4747
} while (0)
4848
#endif /* DBUG_OFF */

storage/innobase/log/log0recv.cc

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
44
Copyright (c) 2012, Facebook Inc.
5-
Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved.
5+
Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
66
77
This program is free software; you can redistribute it and/or modify it under
88
the terms of the GNU General Public License as published by the Free Software
@@ -2848,10 +2848,9 @@ recv_scan_log_recs(
28482848

28492849
recv_init_crash_recovery();
28502850
} else {
2851-
2852-
ib::warn() << "Recovery skipped,"
2853-
" --innodb-read-only set!";
2854-
2851+
ib::warn() << "innodb_read_only"
2852+
" prevents crash recovery";
2853+
recv_needed_recovery = true;
28552854
return(true);
28562855
}
28572856
}
@@ -3263,6 +3262,10 @@ recv_recovery_from_checkpoint_start(
32633262
ut_ad(recv_sys->n_addrs == 0);
32643263
ut_ad(!recv_sys->found_corrupt_fs);
32653264

3265+
if (srv_read_only_mode && recv_needed_recovery) {
3266+
return(DB_READ_ONLY);
3267+
}
3268+
32663269
if (recv_sys->found_corrupt_log && !srv_force_recovery) {
32673270
log_mutex_exit();
32683271
ib::error() << "Found corrupted log when looking checkpoint lsn: "

0 commit comments

Comments
 (0)