MDEV-36236 Instant alter aborts when InnoDB fails to rollback instant operation

Problem:
========
- InnoDB does consecutive instant alter operation, first instant DDL
fails, it fails to reset the old instant information in table during
rollback. This lead to consecutive instant alter to have wrong
assumption about the exisitng instant column information.

Fix:
====
dict_table_t::instant_column(): Duplicate the instant information
field of the table. By doing this, InnoDB alter retains the old
instant information and reset it during rollback operation
This commit is contained in:
Thirunarayanan Balathandayuthapani 2025-04-03 12:19:36 +05:30
commit 0d7ef4f478
4 changed files with 40 additions and 5 deletions

View file

@ -1,8 +1,9 @@
@@ -527,6 +527,6 @@
@@ -576,7 +576,7 @@
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
instants
-37
+38
SET GLOBAL innodb_stats_persistent = @save_stats_persistent;
# End of 10.6 tests
CREATE TABLE t1(f1 INT, f2 TEXT)ENGINE=InnoDB;
INSERT INTO t1 VALUES(1, 'a');
ALTER TABLE t1 ADD COLUMN f3 TEXT FIRST;

View file

@ -577,5 +577,16 @@ FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
instants
37
CREATE TABLE t1(f1 INT, f2 TEXT)ENGINE=InnoDB;
INSERT INTO t1 VALUES(1, 'a');
ALTER TABLE t1 ADD COLUMN f3 TEXT FIRST;
SET STATEMENT DEBUG_DBUG="+d,instant_insert_fail" FOR
ALTER TABLE t1 DROP COLUMN f1;
ERROR HY000: Internal error: InnoDB: Insert into SYS_COLUMNS failed
ALTER TABLE t1 DROP COLUMN f1;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;
SET GLOBAL innodb_stats_persistent = @save_stats_persistent;
# End of 10.6 tests

View file

@ -657,11 +657,19 @@ DROP TABLE t1;
SET DEBUG_SYNC=RESET;
--echo # End of 10.5 tests
SELECT variable_value-@old_instant instants
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
SET GLOBAL innodb_stats_persistent = @save_stats_persistent;
CREATE TABLE t1(f1 INT, f2 TEXT)ENGINE=InnoDB;
INSERT INTO t1 VALUES(1, 'a');
ALTER TABLE t1 ADD COLUMN f3 TEXT FIRST;
--error ER_INTERNAL_ERROR
SET STATEMENT DEBUG_DBUG="+d,instant_insert_fail" FOR
ALTER TABLE t1 DROP COLUMN f1;
ALTER TABLE t1 DROP COLUMN f1;
CHECK TABLE t1;
DROP TABLE t1;
SET GLOBAL innodb_stats_persistent = @save_stats_persistent;
--echo # End of 10.6 tests

View file

@ -621,6 +621,16 @@ inline bool dict_table_t::instant_column(const dict_table_t& table,
}
dict_index_t* index = dict_table_get_first_index(this);
if (instant) {
instant->field_map= static_cast<field_map_element_t*>(
mem_heap_dup(heap, instant->field_map,
(index->n_fields -
index->first_user_field()) *
sizeof *instant->field_map));
instant= static_cast<dict_instant_t*>(
mem_heap_dup(heap, instant, sizeof *instant));
}
bool metadata_changed;
{
const dict_index_t& i = *dict_table_get_first_index(&table);
@ -5515,6 +5525,11 @@ static bool innodb_insert_sys_columns(
return false;
}
DBUG_EXECUTE_IF("instant_insert_fail",
my_error(ER_INTERNAL_ERROR, MYF(0),
"InnoDB: Insert into SYS_COLUMNS failed");
return true;);
if (DB_SUCCESS != que_eval_sql(
info,
"PROCEDURE ADD_COL () IS\n"