MDEV-28806 Assertion `flag == 1' failure in row_build_index_entry_low upon concurrent ALTER and UPDATE

- During online ADD INDEX, InnoDB was incorrectly writing log for an
UPDATE that does not affect the being-created index.
This commit is contained in:
Thirunarayanan Balathandayuthapani 2022-06-13 21:32:06 +05:30
parent 85c0f4d2de
commit eb7e24932b
4 changed files with 58 additions and 6 deletions

View file

@ -124,3 +124,24 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;
#
# MDEV-28806 Assertion `flag == 1' failure in
# row_build_index_entry_low upon concurrent ALTER and UPDATE
#
CREATE TABLE t1(a CHAR(8), b INT, c INT AS (b), KEY(a)) ENGINE=InnoDB;
INSERT INTO t1(b) VALUES (1),(2);
connect con1,localhost,root,,test;
SET DEBUG_SYNC="alter_table_inplace_before_lock_upgrade SIGNAL dml_start WAIT_FOR dml_commit";
ALTER TABLE t1 ADD KEY ind (c);
connection default;
SET DEBUG_SYNC="now WAIT_FOR dml_start";
UPDATE t1 SET a ='foo';
SET DEBUG_SYNC="now SIGNAL dml_commit";
connection con1;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;
disconnect con1;
connection default;
SET DEBUG_SYNC=RESET;

View file

@ -312,4 +312,30 @@ SELECT * FROM t1;
CHECK TABLE t1;
DROP TABLE t1;
--echo #
--echo # MDEV-28806 Assertion `flag == 1' failure in
--echo # row_build_index_entry_low upon concurrent ALTER and UPDATE
--echo #
CREATE TABLE t1(a CHAR(8), b INT, c INT AS (b), KEY(a)) ENGINE=InnoDB;
INSERT INTO t1(b) VALUES (1),(2);
--connect (con1,localhost,root,,test)
SET DEBUG_SYNC="alter_table_inplace_before_lock_upgrade SIGNAL dml_start WAIT_FOR dml_commit";
send ALTER TABLE t1 ADD KEY ind (c);
--connection default
SET DEBUG_SYNC="now WAIT_FOR dml_start";
UPDATE t1 SET a ='foo';
SET DEBUG_SYNC="now SIGNAL dml_commit";
# Cleanup
--connection con1
--reap
CHECK TABLE t1;
DROP TABLE t1;
--disconnect con1
connection default;
SET DEBUG_SYNC=RESET;
--source include/wait_until_count_sessions.inc

View file

@ -4061,6 +4061,11 @@ void UndorecApplier::log_update(const dtuple_t &tuple,
{
if (is_update)
{
/* Ignore the index if the update doesn't affect the index */
if (!row_upd_changes_ord_field_binary(index, update,
nullptr,
row, new_ext))
goto next_index;
dtuple_t *old_entry= row_build_index_entry_low(
old_row, old_ext, index, heap, ROW_BUILD_NORMAL);
@ -4080,6 +4085,7 @@ void UndorecApplier::log_update(const dtuple_t &tuple,
success= row_log_online_op(index, old_entry, 0);
}
}
next_index:
index->lock.s_unlock();
if (!success)
{

View file

@ -1261,9 +1261,6 @@ row_upd_changes_ord_field_binary_func(
ulint i;
const dict_index_t* clust_index;
ut_ad(thr);
ut_ad(thr->graph);
ut_ad(thr->graph->trx);
ut_ad(!index->table->skip_alter_undo);
n_unique = dict_index_get_n_unique(index);
@ -1463,9 +1460,11 @@ row_upd_changes_ord_field_binary_func(
trx_rollback_recovered()
when the server had crashed before
storing the field. */
ut_ad(thr->graph->trx->is_recovered);
ut_ad(thr->graph->trx
== trx_roll_crash_recv_trx);
ut_ad(!thr
|| thr->graph->trx->is_recovered);
ut_ad(!thr
|| thr->graph->trx
== trx_roll_crash_recv_trx);
return(TRUE);
}