MDEV-14711 Assertion `mode == 16 || mode == 12 ||...

MDEV-14711 Assertion `mode == 16 || mode == 12 || !fix_block->page.file_page_was_freed' failed in buf_page_get_gen (rollback requesting a freed undo page)

Problem:
=======
In buf_cur_optimistic_latch_leaves(), requesting a left block with BTR_GET
after releasing current block. But there is no guarantee that left block
could be still available.

Fix:
====

(1) In btr_cur_optimistic_latch_leaves(), replace the BUF_GET with
BUF_GET_POSSIBLY_FREED for fetching left block.
(2) Once InnoDB acquires left block, it should check FIL_PAGE_NEXT with
current block page number. If not, release cursor->left_block and return
false.
parent a3a249c7
...@@ -415,6 +415,7 @@ btr_cur_optimistic_latch_leaves( ...@@ -415,6 +415,7 @@ btr_cur_optimistic_latch_leaves(
{ {
ulint mode; ulint mode;
ulint left_page_no; ulint left_page_no;
ulint curr_page_no;
switch (*latch_mode) { switch (*latch_mode) {
case BTR_SEARCH_LEAF: case BTR_SEARCH_LEAF:
...@@ -441,6 +442,8 @@ btr_cur_optimistic_latch_leaves( ...@@ -441,6 +442,8 @@ btr_cur_optimistic_latch_leaves(
goto unpin_failed; goto unpin_failed;
} }
curr_page_no = block->page.id.page_no();
left_page_no = btr_page_get_prev( left_page_no = btr_page_get_prev(
buf_block_get_frame(block)); buf_block_get_frame(block));
rw_lock_s_unlock(&block->lock); rw_lock_s_unlock(&block->lock);
...@@ -449,11 +452,26 @@ btr_cur_optimistic_latch_leaves( ...@@ -449,11 +452,26 @@ btr_cur_optimistic_latch_leaves(
const page_id_t page_id( const page_id_t page_id(
dict_index_get_space(cursor->index), dict_index_get_space(cursor->index),
left_page_no); left_page_no);
dberr_t err = DB_SUCCESS;
cursor->left_block = btr_block_get( cursor->left_block = buf_page_get_gen(
page_id, page_id,
dict_table_page_size(cursor->index->table), dict_table_page_size(cursor->index->table),
mode, cursor->index, mtr); mode, NULL, BUF_GET_POSSIBLY_FREED,
__FILE__, __LINE__, mtr, &err);
if (err == DB_DECRYPTION_FAILED) {
cursor->index->table->file_unreadable = true;
}
if (btr_page_get_next(buf_block_get_frame(
cursor->left_block))
!= curr_page_no) {
/* release the left block */
btr_leaf_page_release(
cursor->left_block, mode, mtr);
return false;
}
} else { } else {
cursor->left_block = NULL; cursor->left_block = NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment