Skip to content

Commit eaeb8ec

Browse files
committed
MDEV-24653 Assertion block->page.id.page_no() == index->page failed in innobase_add_instant_try()
We may end up with an empty leaf page (containing only an ADD COLUMN metadata record) that is not the root page. innobase_add_instant_try(): Disable an optimization for a non-canonical empty table that contains a metadata record somewhere else than in the root page. btr_pcur_store_position(): Tolerate a non-canonical empty table.
1 parent 0e10d7e commit eaeb8ec

File tree

4 files changed

+61
-10
lines changed

4 files changed

+61
-10
lines changed

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,6 @@ a b vb
263263
4 NULL NULL
264264
5 NULL NULL
265265
DROP TABLE t1;
266-
SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;
267266
#
268267
# MDEV-21045 AddressSanitizer: use-after-poison in mem_heap_dup / row_log_table_get_pk_col
269268
#
@@ -282,3 +281,21 @@ connection default;
282281
SET DEBUG_SYNC='RESET';
283282
disconnect con2;
284283
DROP TABLE t1;
284+
#
285+
# MDEV-24653 Assertion block->page.id.page_no() == index->page failed
286+
# in innobase_add_instant_try()
287+
#
288+
SET @saved_limit = @@GLOBAL.innodb_limit_optimistic_insert_debug;
289+
SET GLOBAL innodb_limit_optimistic_insert_debug = 2;
290+
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
291+
INSERT INTO t1 VALUES (1),(2),(3),(4);
292+
ALTER TABLE t1 ADD COLUMN b INT;
293+
DELETE FROM t1;
294+
InnoDB 0 transactions not purged
295+
ALTER TABLE t1 ADD COLUMN c INT;
296+
SELECT * FROM t1;
297+
a b c
298+
DROP TABLE t1;
299+
SET GLOBAL innodb_limit_optimistic_insert_debug = @saved_limit;
300+
# End of 10.3 tests
301+
SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,6 @@ CHECK TABLE t1;
292292
SELECT * FROM t1;
293293
DROP TABLE t1;
294294

295-
SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;
296-
297295
--echo #
298296
--echo # MDEV-21045 AddressSanitizer: use-after-poison in mem_heap_dup / row_log_table_get_pk_col
299297
--echo #
@@ -319,3 +317,26 @@ SET DEBUG_SYNC='now SIGNAL update';
319317
SET DEBUG_SYNC='RESET';
320318
--disconnect con2
321319
DROP TABLE t1;
320+
321+
--echo #
322+
--echo # MDEV-24653 Assertion block->page.id.page_no() == index->page failed
323+
--echo # in innobase_add_instant_try()
324+
--echo #
325+
326+
SET @saved_limit = @@GLOBAL.innodb_limit_optimistic_insert_debug;
327+
SET GLOBAL innodb_limit_optimistic_insert_debug = 2;
328+
329+
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
330+
INSERT INTO t1 VALUES (1),(2),(3),(4);
331+
ALTER TABLE t1 ADD COLUMN b INT;
332+
DELETE FROM t1;
333+
--source include/wait_all_purged.inc
334+
ALTER TABLE t1 ADD COLUMN c INT;
335+
336+
SELECT * FROM t1;
337+
DROP TABLE t1;
338+
SET GLOBAL innodb_limit_optimistic_insert_debug = @saved_limit;
339+
340+
--echo # End of 10.3 tests
341+
342+
SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;

storage/innobase/btr/btr0pcur.cc

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2016, 2020, MariaDB Corporation.
4+
Copyright (c) 2016, 2021, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -128,13 +128,14 @@ btr_pcur_store_position(
128128
cursor->old_stored = true;
129129

130130
if (page_is_empty(block->frame)) {
131+
ut_ad(block->page.id.page_no() == index->page);
132+
empty_table:
131133
/* It must be an empty index tree; NOTE that in this case
132134
we do not store the modify_clock, but always do a search
133135
if we restore the cursor position */
134136

135137
ut_a(!page_has_siblings(block->frame));
136138
ut_ad(page_is_leaf(block->frame));
137-
ut_ad(block->page.id.page_no() == index->page);
138139

139140
if (page_rec_is_supremum_low(offs)) {
140141
cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
@@ -150,7 +151,15 @@ btr_pcur_store_position(
150151
rec = page_rec_get_prev(rec);
151152

152153
ut_ad(!page_rec_is_infimum(rec));
153-
ut_ad(!rec_is_metadata(rec, index));
154+
155+
if (UNIV_UNLIKELY(rec_is_metadata(rec, index))) {
156+
/* The table may be empty such that it only
157+
contains a metadata record, in a leaf page
158+
that is not the root page. */
159+
ut_ad(index->is_primary());
160+
ut_ad(block->page.id.page_no() != index->page);
161+
goto empty_table;
162+
}
154163

155164
cursor->rel_pos = BTR_PCUR_AFTER;
156165
} else if (page_rec_is_infimum_low(offs)) {
@@ -160,7 +169,9 @@ btr_pcur_store_position(
160169
ut_ad(!page_has_prev(block->frame));
161170
rec = page_rec_get_next(rec);
162171
if (page_rec_is_supremum(rec)) {
163-
ut_ad(page_has_next(block->frame));
172+
ut_ad(page_has_next(block->frame)
173+
|| block->page.id.page_no()
174+
!= index->page);
164175
goto before_first;
165176
}
166177
}

storage/innobase/handler/handler0alter.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 2005, 2019, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2013, 2020, MariaDB Corporation.
4+
Copyright (c) 2013, 2021, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -4482,11 +4482,13 @@ innobase_add_instant_try(
44824482
const rec_t* rec = btr_pcur_get_rec(&pcur);
44834483
que_thr_t* thr = pars_complete_graph_for_exec(
44844484
NULL, trx, ctx->heap, NULL);
4485+
const bool is_root = block->page.id.page_no() == index->page;
44854486

44864487
dberr_t err;
44874488
if (rec_is_metadata(rec, index)) {
44884489
ut_ad(page_rec_is_user_rec(rec));
4489-
if (!page_has_next(block->frame)
4490+
if (is_root
4491+
&& !page_has_next(block->frame)
44904492
&& page_rec_is_last(rec, block->frame)) {
44914493
goto empty_table;
44924494
}
@@ -4528,7 +4530,7 @@ innobase_add_instant_try(
45284530
}
45294531
btr_pcur_close(&pcur);
45304532
goto func_exit;
4531-
} else if (page_rec_is_supremum(rec)) {
4533+
} else if (is_root && page_rec_is_supremum(rec)) {
45324534
empty_table:
45334535
/* The table is empty. */
45344536
ut_ad(fil_page_index_page_check(block->frame));

0 commit comments

Comments
 (0)