Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
10.6
-
None
Description
In MDEV-35626, marko found an independent issue which could skip deleting change buffer records while reusing an old freed page on disk. The code in question is is buf_page_create_low(), specific to compressed row format. Here we over-write ibuf_exist using the latest state incorrectly. The ibuf_exists has already been set earlier.
else
|
{
|
auto state= bpage->state();
|
ut_ad(state >= buf_page_t::FREED);
|
ut_ad(state < buf_page_t::READ_FIX);
|
|
page_hash_latch &hash_lock= buf_pool.page_hash.lock_get(chain);
|
/* It does not make sense to use transactional_lock_guard here,
|
because buf_relocate() would likely make the memory transaction
|
too large. */
|
hash_lock.lock();
|
|
if (state < buf_page_t::UNFIXED)
|
bpage->set_reinit(buf_page_t::FREED);
|
else
|
{
|
bpage->set_reinit(state & buf_page_t::LRU_MASK);
|
ibuf_exist= (state & buf_page_t::LRU_MASK) == buf_page_t::IBUF_EXIST;
|
}
|
If old change buffer records are not removed it could potentially be reapplied and cause damage to the secondary index.
I could repeat the flow by modifying the test in MDEV-32489.
1. Compressed row format table with secondary index.
2. Force Insert buffering in debug mode to insert rows to change buffer
3. Drop the index
4. Create the index again and while creating new pages, force load the old page with only the compressed part in buf_page_create_low. In real user case it could happen by buf_read_ahead_random, buf_read_ahead_linear.
This demonstrates the case where buf_page_create_low skipping the ibuf_merge_or_delete_for_page call after ibuf_exist gets over-written from TRUE to FALSE.
However, in continuation of the "Create Index" flow, BtrBulk::finish calls ibuf_delete_recs() to delete any old change buffer records from the page. So, we are saved in this path and no real issue could be reported.
I tried a few other cases using truncate but could not repeat any real issue. Either way, the code fragment is potentially problematic and needs to be fixed.
Here is the patch.
https://github.com/MariaDB/server/pull/3712/