Skip to content

Commit eb7e249

Browse files
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.
1 parent 85c0f4d commit eb7e249

File tree

4 files changed

+58
-6
lines changed

4 files changed

+58
-6
lines changed

mysql-test/suite/gcol/r/innodb_virtual_debug.result

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,24 @@ CHECK TABLE t1;
124124
Table Op Msg_type Msg_text
125125
test.t1 check status OK
126126
DROP TABLE t1;
127+
#
128+
# MDEV-28806 Assertion `flag == 1' failure in
129+
# row_build_index_entry_low upon concurrent ALTER and UPDATE
130+
#
131+
CREATE TABLE t1(a CHAR(8), b INT, c INT AS (b), KEY(a)) ENGINE=InnoDB;
132+
INSERT INTO t1(b) VALUES (1),(2);
133+
connect con1,localhost,root,,test;
134+
SET DEBUG_SYNC="alter_table_inplace_before_lock_upgrade SIGNAL dml_start WAIT_FOR dml_commit";
135+
ALTER TABLE t1 ADD KEY ind (c);
136+
connection default;
137+
SET DEBUG_SYNC="now WAIT_FOR dml_start";
138+
UPDATE t1 SET a ='foo';
139+
SET DEBUG_SYNC="now SIGNAL dml_commit";
140+
connection con1;
141+
CHECK TABLE t1;
142+
Table Op Msg_type Msg_text
143+
test.t1 check status OK
144+
DROP TABLE t1;
145+
disconnect con1;
146+
connection default;
147+
SET DEBUG_SYNC=RESET;

mysql-test/suite/gcol/t/innodb_virtual_debug.test

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,4 +312,30 @@ SELECT * FROM t1;
312312
CHECK TABLE t1;
313313
DROP TABLE t1;
314314

315+
--echo #
316+
--echo # MDEV-28806 Assertion `flag == 1' failure in
317+
--echo # row_build_index_entry_low upon concurrent ALTER and UPDATE
318+
--echo #
319+
320+
CREATE TABLE t1(a CHAR(8), b INT, c INT AS (b), KEY(a)) ENGINE=InnoDB;
321+
INSERT INTO t1(b) VALUES (1),(2);
322+
323+
--connect (con1,localhost,root,,test)
324+
SET DEBUG_SYNC="alter_table_inplace_before_lock_upgrade SIGNAL dml_start WAIT_FOR dml_commit";
325+
send ALTER TABLE t1 ADD KEY ind (c);
326+
327+
--connection default
328+
SET DEBUG_SYNC="now WAIT_FOR dml_start";
329+
UPDATE t1 SET a ='foo';
330+
SET DEBUG_SYNC="now SIGNAL dml_commit";
331+
332+
# Cleanup
333+
--connection con1
334+
--reap
335+
CHECK TABLE t1;
336+
DROP TABLE t1;
337+
--disconnect con1
338+
connection default;
339+
SET DEBUG_SYNC=RESET;
340+
315341
--source include/wait_until_count_sessions.inc

storage/innobase/row/row0log.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4061,6 +4061,11 @@ void UndorecApplier::log_update(const dtuple_t &tuple,
40614061
{
40624062
if (is_update)
40634063
{
4064+
/* Ignore the index if the update doesn't affect the index */
4065+
if (!row_upd_changes_ord_field_binary(index, update,
4066+
nullptr,
4067+
row, new_ext))
4068+
goto next_index;
40644069
dtuple_t *old_entry= row_build_index_entry_low(
40654070
old_row, old_ext, index, heap, ROW_BUILD_NORMAL);
40664071

@@ -4080,6 +4085,7 @@ void UndorecApplier::log_update(const dtuple_t &tuple,
40804085
success= row_log_online_op(index, old_entry, 0);
40814086
}
40824087
}
4088+
next_index:
40834089
index->lock.s_unlock();
40844090
if (!success)
40854091
{

storage/innobase/row/row0upd.cc

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,9 +1261,6 @@ row_upd_changes_ord_field_binary_func(
12611261
ulint i;
12621262
const dict_index_t* clust_index;
12631263

1264-
ut_ad(thr);
1265-
ut_ad(thr->graph);
1266-
ut_ad(thr->graph->trx);
12671264
ut_ad(!index->table->skip_alter_undo);
12681265

12691266
n_unique = dict_index_get_n_unique(index);
@@ -1463,9 +1460,11 @@ row_upd_changes_ord_field_binary_func(
14631460
trx_rollback_recovered()
14641461
when the server had crashed before
14651462
storing the field. */
1466-
ut_ad(thr->graph->trx->is_recovered);
1467-
ut_ad(thr->graph->trx
1468-
== trx_roll_crash_recv_trx);
1463+
ut_ad(!thr
1464+
|| thr->graph->trx->is_recovered);
1465+
ut_ad(!thr
1466+
|| thr->graph->trx
1467+
== trx_roll_crash_recv_trx);
14691468
return(TRUE);
14701469
}
14711470

0 commit comments

Comments
 (0)