diff options
author | Vlad Lesin <vlad_lesin@mail.ru> | 2022-04-14 14:27:23 +0300 |
---|---|---|
committer | Vlad Lesin <vlad_lesin@mail.ru> | 2022-04-14 15:23:35 +0300 |
commit | 4a70aa8e1b3cba9c92b0cd0a16a3730411151472 (patch) | |
tree | 402284841811f8a8cc894301722506860c2b9940 | |
parent | 2aed566d2267a824158025c09830bc6353ec88a9 (diff) | |
download | mariadb-git-bb-10.6-MDEV-17843-lock_rec_queue_validate.tar.gz |
MDEV-17843 Assertion `page_rec_is_leaf(rec)' failed in lock_rec_queue_validate upon SHOW ENGINE INNODB STATUSbb-10.6-MDEV-17843-lock_rec_queue_validate
lock_validate() accumulates page ids under locked LockMutexGuard, 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.
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 26 |
1 files changed, 10 insertions, 16 deletions
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 05fdf9b3efe..fa2a5fc5d91 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -4750,25 +4750,25 @@ loop: holding a tablespace latch. */ if (!latched) 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 (i == PAGE_HEAP_NO_SUPREMUM || locked) { rec = page_find_rec_with_heap_no(block->page.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, id, 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, id, rec, lock->index, + offsets); + } nth_bit = i + 1; @@ -4850,12 +4850,6 @@ static void lock_rec_block_validate(const page_id_t page_id) BUF_GET_POSSIBLY_FREED, &mtr, &err); - if (err != DB_SUCCESS) { - ib::error() << "Lock rec block validate failed for tablespace " - << space->chain.start->name - << page_id << " err " << err; - } - ut_ad(!block || block->page.is_freed() || lock_rec_validate_page(block, space->is_latched())); |