diff --git a/mysql-test/suite/innodb/r/innodb-index-online.result b/mysql-test/suite/innodb/r/innodb-index-online.result index 5a287e58d8a..eb1daa5a2d3 100644 --- a/mysql-test/suite/innodb/r/innodb-index-online.result +++ b/mysql-test/suite/innodb/r/innodb-index-online.result @@ -534,7 +534,6 @@ INSERT INTO t1 VALUES(1,1); ROLLBACK; SET DEBUG_SYNC = 'now SIGNAL inserted'; connection con1; -disconnect con1; connection default; SELECT * FROM t1; a b @@ -543,6 +542,31 @@ CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK DROP TABLE t1; +# +# MDEV-36281 DML aborts during online virtual index +# +CREATE TABLE t1(f1 INT NOT NULL PRIMARY KEY, f2 INT NOT NULL, +f3 INT NOT NULL, f4 INT AS (f3) VIRTUAL, +f5 INT AS (f1) VIRTUAL, INDEX(f4))ENGINE=InnoDB; +INSERT INTO t1(f1, f2, f3) VALUES(1, 2, 3); +SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL dml_start WAIT_FOR dml_finish'; +ALTER TABLE t1 ADD INDEX v1(f5, f2, f4), ADD INDEX v2(f3, f5); +connection con1; +set DEBUG_SYNC="now WAIT_FOR dml_start"; +UPDATE t1 SET f3= f3 + 1; +set DEBUG_SYNC="now SIGNAL dml_finish"; +disconnect con1; +connection default; +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +SELECT f5, f2, f4 FROM t1 USE INDEX(v1); +f5 f2 f4 +1 2 4 +SELECT f3, f5 FROM t1 USE INDEX(v2); +f3 f5 +4 1 +DROP TABLE t1; SET DEBUG_SYNC = 'RESET'; SET GLOBAL innodb_file_per_table = @global_innodb_file_per_table_orig; SET GLOBAL innodb_monitor_enable = default; diff --git a/mysql-test/suite/innodb/t/innodb-index-online.test b/mysql-test/suite/innodb/t/innodb-index-online.test index 96ee3149518..97ca25b1420 100644 --- a/mysql-test/suite/innodb/t/innodb-index-online.test +++ b/mysql-test/suite/innodb/t/innodb-index-online.test @@ -510,12 +510,35 @@ SET DEBUG_SYNC = 'now SIGNAL inserted'; connection con1; reap; -disconnect con1; connection default; SELECT * FROM t1; CHECK TABLE t1; DROP TABLE t1; + +--echo # +--echo # MDEV-36281 DML aborts during online virtual index +--echo # +CREATE TABLE t1(f1 INT NOT NULL PRIMARY KEY, f2 INT NOT NULL, + f3 INT NOT NULL, f4 INT AS (f3) VIRTUAL, + f5 INT AS (f1) VIRTUAL, INDEX(f4))ENGINE=InnoDB; +INSERT INTO t1(f1, f2, f3) VALUES(1, 2, 3); +SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL dml_start WAIT_FOR dml_finish'; +send ALTER TABLE t1 ADD INDEX v1(f5, f2, f4), ADD INDEX v2(f3, f5); + +connection con1; +set DEBUG_SYNC="now WAIT_FOR dml_start"; +UPDATE t1 SET f3= f3 + 1; +set DEBUG_SYNC="now SIGNAL dml_finish"; + +disconnect con1; +connection default; +reap; +CHECK TABLE t1 EXTENDED; +SELECT f5, f2, f4 FROM t1 USE INDEX(v1); +SELECT f3, f5 FROM t1 USE INDEX(v2); +DROP TABLE t1; + SET DEBUG_SYNC = 'RESET'; # Check that all connections opened by test cases in this file are really diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 6f3425aab17..702e7098839 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -4065,14 +4065,7 @@ void UndorecApplier::log_update(const dtuple_t &tuple, if (!(this->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { for (ulint i = 0; i < dict_table_get_n_v_cols(table); i++) - dfield_get_type( - dtuple_get_nth_v_field(row, i))->mtype = DATA_MISSING; - } - - if (is_update) - { - old_row= dtuple_copy(row, heap); - row_upd_replace(old_row, &old_ext, clust_index, update, heap); + dfield_get_type(dtuple_get_nth_v_field(row, i))->mtype = DATA_MISSING; } if (table->n_v_cols) @@ -4080,6 +4073,12 @@ void UndorecApplier::log_update(const dtuple_t &tuple, (cmpl_info & UPD_NODE_NO_ORD_CHANGE) ? nullptr : undo_rec); + if (is_update) + { + old_row= dtuple_copy(row, heap); + row_upd_replace(old_row, &old_ext, clust_index, update, heap); + } + bool success= true; dict_index_t *index= dict_table_get_next_index(clust_index); while (index)