Skip to content

Commit

Permalink
MDEV-17843 Assertion `page_rec_is_leaf(rec)' failed in lock_rec_queue…
Browse files Browse the repository at this point in the history
…_validate upon SHOW ENGINE INNODB STATUS

lock_validate() accumulates page ids under locked lock_sys->mutex, then
releases the latch, and invokes lock_rec_block_validate() for each page.
Some other thread has ability to add/remove locks and change pages
between releasing the latch in lock_validate() and acquiring it in
lock_rec_validate_page().

lock_rec_validate_page() can invoke lock_rec_queue_validate() for
non-locked supremum, what can cause ut_ad(page_rec_is_leaf(rec)) failure
in lock_rec_queue_validate().

The fix is to invoke lock_rec_queue_validate() only for locked records
in lock_rec_validate_page().

The error message in lock_rec_block_validate() is not necessary as
BUF_GET_POSSIBLY_FREED mode is used to get block from buffer pool, and
this is not error if a block was evicted.

The test case would require new debug sync point. I think it's not
necessary as the fixed code is debug-only.
  • Loading branch information
vlad-lesin committed May 4, 2022
1 parent 9614fde commit 2c381d8
Showing 1 changed file with 10 additions and 17 deletions.
27 changes: 10 additions & 17 deletions storage/innobase/lock/lock0lock.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5050,25 +5050,25 @@ lock_rec_validate_page(
holding a space->latch. */
if (!sync_check_find(SYNC_FSP))
for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) {

if (i == PAGE_HEAP_NO_SUPREMUM
|| lock_rec_get_nth_bit(lock, i)) {
bool locked = lock_rec_get_nth_bit(lock, i);
if (locked || i == PAGE_HEAP_NO_SUPREMUM) {

rec = page_find_rec_with_heap_no(block->frame, i);
ut_a(rec);
ut_ad(!lock_rec_get_nth_bit(lock, i)
|| page_rec_is_leaf(rec));
offsets = rec_get_offsets(rec, lock->index, offsets,
lock->index->n_core_fields,
ULINT_UNDEFINED, &heap);
ut_ad(!locked || page_rec_is_leaf(rec));

/* If this thread is holding the file space
latch (fil_space_t::latch), the following
check WILL break the latching order and may
cause a deadlock of threads. */

lock_rec_queue_validate(
TRUE, block, rec, lock->index, offsets);
if (locked) {
offsets = rec_get_offsets(rec, lock->index,
offsets, lock->index->n_core_fields,
ULINT_UNDEFINED, &heap);
lock_rec_queue_validate(TRUE, block, rec,
lock->index, offsets);
}

nth_bit = i + 1;

Expand Down Expand Up @@ -5161,13 +5161,6 @@ lock_rec_block_validate(
BUF_GET_POSSIBLY_FREED,
__FILE__, __LINE__, &mtr, &err);

if (err != DB_SUCCESS) {
ib::error() << "Lock rec block validate failed for tablespace "
<< space->name
<< " space_id " << space_id
<< " page_no " << page_no << " err " << err;
}

if (block) {
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);

Expand Down

0 comments on commit 2c381d8

Please sign in to comment.