diff options
author | Vlad Lesin <vlad_lesin@mail.ru> | 2022-04-14 14:27:23 +0300 |
---|---|---|
committer | Vlad Lesin <vlad_lesin@mail.ru> | 2022-05-04 12:51:28 +0300 |
commit | 2c381d8cf65ad46936045fb7ee141de4e392cde7 (patch) | |
tree | 774d5f66af4af7bfd130670080d43d8cd698e7f0 /storage | |
parent | 9614fde1aac6ffa4745804342ff70a96b2418e30 (diff) | |
download | mariadb-git-2c381d8cf65ad46936045fb7ee141de4e392cde7.tar.gz |
MDEV-17843 Assertion `page_rec_is_leaf(rec)' failed in lock_rec_queue_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.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 27 |
1 files changed, 10 insertions, 17 deletions
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 3398f09b772..2fd2ef94365 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -5050,25 +5050,25 @@ loop: 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; @@ -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); |