Skip to content

Commit d2e649a

Browse files
committed
MDEV-29440 InnoDB instant ALTER TABLE recovery must use READ UNCOMMITTED
In commit 8f8ba75 (MDEV-27234) the data dictionary recovery was changed to use READ COMMITTED so that table-rebuild operations (OPTIMIZE TABLE, TRUNCATE TABLE, some forms of ALTER TABLE) would be recovered correctly. However, for operations that avoid a table rebuild thanks to being able to instantly ADD, DROP or reorder columns, recovery must use the READ UNCOMMITTED isolation level so that changes to the hidden metadata record can be rolled back. We will detect instant operations by detecting uncommitted changes to SYS_COLUMNS in case there is no uncommitted change of SYS_TABLES.ID for the table. In any table-rebuilding DDL operation, the SYS_TABLES.ID (and likely also the table name) will be updated. As part of rolling back the instant ALTER TABLE operation, after the operation on the hidden metadata record has been rolled back, a rollback of an INSERT into SYS_COLUMNS in row_undo_ins_remove_clust_rec() will invoke trx_t::evict_table() to discard the READ UNCOMMITTED definition of the table. After that, subsequent recovery steps will load and use the correct table definition. Reviewed by: Thirunarayanan Balathandayuthapani Tested by: Matthias Leich
1 parent 0fa4dd0 commit d2e649a

File tree

8 files changed

+234
-131
lines changed

8 files changed

+234
-131
lines changed

mysql-test/suite/innodb/r/instant_alter_crash.result

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,5 +176,25 @@ t3 CREATE TABLE `t3` (
176176
PRIMARY KEY (`id`),
177177
UNIQUE KEY `v2` (`v2`)
178178
) ENGINE=InnoDB DEFAULT CHARSET=latin1
179-
DROP TABLE t1,t2,t3;
179+
DROP TABLE t2,t3;
180+
#
181+
# MDEV-29440 InnoDB instant ALTER TABLE recovery wrongly uses
182+
# READ COMMITTED isolation level instead of READ UNCOMMITTED
183+
#
184+
CREATE TABLE t2(a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB;
185+
INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6);
186+
connect ddl, localhost, root;
187+
SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever';
188+
ALTER TABLE t2 ADD COLUMN b TINYINT UNSIGNED NOT NULL DEFAULT 42 FIRST;
189+
connection default;
190+
SET DEBUG_SYNC='now WAIT_FOR ddl';
191+
SET GLOBAL innodb_flush_log_at_trx_commit=1;
192+
DELETE FROM t1;
193+
# Kill the server
194+
disconnect ddl;
195+
# restart
196+
CHECK TABLE t2;
197+
Table Op Msg_type Msg_text
198+
test.t2 check status OK
199+
DROP TABLE t1,t2;
180200
db.opt

mysql-test/suite/innodb/t/instant_alter_crash.test

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,30 @@ disconnect ddl;
198198
SHOW CREATE TABLE t1;
199199
SHOW CREATE TABLE t2;
200200
SHOW CREATE TABLE t3;
201-
DROP TABLE t1,t2,t3;
201+
DROP TABLE t2,t3;
202+
203+
--echo #
204+
--echo # MDEV-29440 InnoDB instant ALTER TABLE recovery wrongly uses
205+
--echo # READ COMMITTED isolation level instead of READ UNCOMMITTED
206+
--echo #
207+
CREATE TABLE t2(a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB;
208+
INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6);
209+
210+
connect ddl, localhost, root;
211+
SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever';
212+
--send
213+
ALTER TABLE t2 ADD COLUMN b TINYINT UNSIGNED NOT NULL DEFAULT 42 FIRST;
214+
215+
connection default;
216+
SET DEBUG_SYNC='now WAIT_FOR ddl';
217+
SET GLOBAL innodb_flush_log_at_trx_commit=1;
218+
DELETE FROM t1;
219+
220+
--source include/kill_mysqld.inc
221+
disconnect ddl;
222+
--source include/start_mysqld.inc
223+
224+
CHECK TABLE t2;
225+
DROP TABLE t1,t2;
202226

203227
--list_files $MYSQLD_DATADIR/test

0 commit comments

Comments
 (0)