1# Crash-safe InnoDB ALTER operations
2
3--source include/not_valgrind.inc
4--source include/have_debug.inc
5--source include/not_crashrep.inc
6
7--disable_query_log
8call mtr.add_suppression(' Cannot find a free slot for an undo log');
9call mtr.add_suppression(' row_merge_rename_index_to_add failed with error 47');
10call mtr.add_suppression(' Flagged corruption of `c[23]`');
11call mtr.add_suppression(' Index `c[23]` .*is corrupted');
12--enable_query_log
13
14--echo #
15--echo # Bug#20015132 ALTER TABLE FAILS TO CHECK IF TABLE IS CORRUPTED
16--echo #
17
18CREATE TABLE t1(c1 INT PRIMARY KEY, c2 CHAR(1), c3 INT UNSIGNED) ENGINE=InnoDB;
19--disable_testcase BUG#0000
20SET DEBUG='+d,ib_create_table_fail_too_many_trx';
21--error ER_TOO_MANY_CONCURRENT_TRXS
22ALTER TABLE t1 ADD INDEX (c2), ADD INDEX (c3);
23
24SET DEBUG='-d,ib_create_table_fail_too_many_trx';
25--enable_testcase
26ALTER TABLE t1 ADD INDEX (c2), ADD INDEX (c3);
27# Flag the secondary indexes corrupted.
28SET DEBUG='+d,dict_set_index_corrupted';
29CHECK TABLE t1;
30
31# Ensure that the corruption is permanent.
32--source include/restart_mysqld.inc
33CHECK TABLE t1;
34ALTER TABLE t1 DROP INDEX c2;
35CHECK TABLE t1;
36# We refuse an ALTER TABLE that would modify the InnoDB data dictionary
37# while leaving some of the table corrupted.
38--error ER_CHECK_NO_SUCH_TABLE
39ALTER TABLE t1 ADD INDEX (c2,c3);
40# This will rebuild the table, uncorrupting all secondary indexes.
41ALTER TABLE t1 CHANGE c3 c3 INT NOT NULL;
42CHECK TABLE t1;
43ALTER TABLE t1 ADD INDEX (c2,c3);
44DROP TABLE t1;
45
46let $MYSQLD_DATADIR= `select @@datadir`;
47let datadir= `select @@datadir`;
48
49# These are from include/shutdown_mysqld.inc and allow to call start_mysqld.inc
50--let $_server_id= `SELECT @@server_id`
51--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect
52
53--echo #
54--echo # Bug #14669848 CRASH DURING ALTER MAKES ORIGINAL TABLE INACCESSIBLE
55--echo #
56--echo # -- Scenario 1:
57--echo # Crash the server in ha_innobase::commit_inplace_alter_table()
58--echo # just after committing the dictionary changes.
59
60CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL) ENGINE=innodb;
61INSERT INTO t1 VALUES (1,2),(3,4);
62SET DEBUG='d,innodb_alter_commit_crash_after_commit';
63
64let $orig_table_id = `SELECT table_id
65	FROM information_schema.innodb_tables
66	WHERE name = 'test/t1'`;
67
68# Write file to make mysql-test-run.pl expect crash
69--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
70
71--error 2013
72ALTER TABLE t1 ADD PRIMARY KEY (f2, f1);
73
74--echo # Restart mysqld after the crash and reconnect.
75--source include/start_mysqld.inc
76
77let $temp_table_name = `SELECT SUBSTR(name, 6)
78	FROM information_schema.innodb_tables
79	WHERE table_id = $orig_table_id`;
80
81--echo # Files in datadir after manual recovery.
82--list_files $MYSQLD_DATADIR/test
83
84SHOW TABLES;
85SHOW CREATE TABLE t1;
86INSERT INTO t1 VALUES (5,6),(7,8);
87SELECT * FROM t1;
88DROP TABLE t1;
89
90CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL) ENGINE=InnoDB;
91ALTER TABLE t1 ADD PRIMARY KEY (f2, f1);
92DROP TABLE t1;
93
94--echo # -- Scenario 2:
95--echo # Crash the server in ha_innobase::commit_inplace_alter_table()
96--echo # just before committing the dictionary changes, but after
97--echo # writing the MLOG_FILE_RENAME records. As the mini-transaction
98--echo # is not committed, the renames will not be replayed.
99
100CREATE TABLE t2 (f1 int not null, f2 int not null) ENGINE=InnoDB;
101INSERT INTO t2 VALUES (1,2),(3,4);
102SET DEBUG='d,innodb_alter_commit_crash_before_commit';
103
104let $orig_table_id = `SELECT table_id
105	FROM information_schema.innodb_tables
106	WHERE name = 'test/t2'`;
107
108# Write file to make mysql-test-run.pl expect crash
109--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
110
111--error 2013
112ALTER TABLE t2 ADD PRIMARY KEY (f2, f1);
113
114--echo # Startup the server after the crash
115--source include/start_mysqld.inc
116
117SHOW TABLES;
118INSERT INTO t2 VALUES (5,6),(7,8);
119SELECT * from t2;
120SHOW CREATE TABLE t2;
121DROP TABLE t2;
122
123CREATE TABLE t2 (f1 INT NOT NULL, f2 INT NOT NULL) ENGINE=InnoDB;
124ALTER TABLE t2 ADD PRIMARY KEY (f2, f1);
125DROP TABLE t2;
126--list_files $MYSQLD_DATADIR/test
127
128--echo # -------------------------
129--echo # End of Testing Scenario 2
130--echo # -------------------------
131
132--echo #
133--echo # Bug#19330255 CRASH DURING ALTER TABLE LEADS TO
134--echo # DATA DICTIONARY INCONSISTENCY
135--echo #
136
137CREATE TABLE t1(a int PRIMARY KEY, b varchar(150), c int NOT NULL);
138INSERT INTO t1 SET a=1,c=2;
139SET DEBUG='d,innodb_alter_commit_crash_after_commit';
140
141let $orig_table_id = `select table_id from
142  information_schema.innodb_tables where name = 'test/t1'`;
143
144# Write file to make mysql-test-run.pl expect crash
145--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
146
147--error 2013
148ALTER TABLE t1 ADD INDEX (b), CHANGE c d int;
149
150--echo # Restart mysqld after the crash and reconnect.
151--source include/start_mysqld.inc
152
153--echo # Files in datadir after manual recovery.
154--list_files $MYSQLD_DATADIR/test
155
156SHOW TABLES;
157SHOW CREATE TABLE t1;
158SELECT * FROM t1;
159DROP TABLE t1;
160