Commit e8fa04ce authored by Annamalai Gurusami's avatar Annamalai Gurusami

Bug #16806366 BOGUS CALL TO LOCK_REC_RESTORE_FROM_PAGE_INFIMUM IN

INSERT BUFFER MERGE

Problem:

When the record is merged from the change buffer to the actual page,
in a particular condition, it is assumed that the deleted rec will
be re-used by the inserted rec.  With this assumption the lock is
restored on the pointer to the deleted rec itself, thinking that
it is pointing to the newly inserted rec.

Solution:

Just before restoring the lock, update the rec pointer to point
to the newly inserted record.  An assert has been added to verify
this.  This assert will fail without the fix and will pass with
the fix.

rb#2449 in review by Marko and Jimmy

parent 205bf59a
/*****************************************************************************
Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
/******************************************************
Insert buffer
......@@ -29,6 +47,7 @@ Created 7/19/1997 Heikki Tuuri
#include "lock0lock.h"
#include "log0recv.h"
#include "que0que.h"
#include "rem0cmp.h"
/* STRUCTURE OF AN INSERT BUFFER RECORD
......@@ -2837,9 +2856,10 @@ ibuf_insert(
During merge, inserts to an index page a secondary index entry extracted
from the insert buffer. */
static
void
rec_t*
ibuf_insert_to_index_page_low(
/*==========================*/
/* out: newly inserted record */
dtuple_t* entry, /* in: buffered entry to insert */
page_t* page, /* in: index page where the buffered entry
should be placed */
......@@ -2852,10 +2872,13 @@ ibuf_insert_to_index_page_low(
ulint page_no;
page_t* bitmap_page;
ulint old_bits;
rec_t* rec;
DBUG_ENTER("ibuf_insert_to_index_page_low");
if (UNIV_LIKELY
(page_cur_tuple_insert(page_cur, entry, index, mtr) != NULL)) {
return;
rec = page_cur_tuple_insert(page_cur, entry, index, mtr);
if (rec != NULL) {
DBUG_RETURN(rec);
}
/* If the record did not fit, reorganize */
......@@ -2866,9 +2889,10 @@ ibuf_insert_to_index_page_low(
/* This time the record must fit */
if (UNIV_LIKELY
(page_cur_tuple_insert(page_cur, entry, index, mtr) != NULL)) {
return;
rec = page_cur_tuple_insert(page_cur, entry, index, mtr);
if (rec != NULL) {
DBUG_RETURN(rec);
}
ut_print_timestamp(stderr);
......@@ -2897,6 +2921,8 @@ ibuf_insert_to_index_page_low(
fputs("InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
DBUG_RETURN(NULL);
}
/************************************************************************
......@@ -2916,6 +2942,8 @@ ibuf_insert_to_index_page(
ulint low_match;
rec_t* rec;
DBUG_ENTER("ibuf_insert_to_index_page");
ut_ad(ibuf_inside());
ut_ad(dtuple_check_typed(entry));
ut_ad(!buf_block_align(page)->is_hashed);
......@@ -2950,7 +2978,7 @@ dump:
"InnoDB: Submit a detailed bug report to"
" http://bugs.mysql.com!\n", stderr);
return;
DBUG_VOID_RETURN;
}
low_match = page_cur_search(page, index, entry,
......@@ -2981,7 +3009,7 @@ dump:
btr_cur_set_deleted_flag_for_ibuf(rec, FALSE, mtr);
updated_in_place:
mem_heap_free(heap);
return;
DBUG_VOID_RETURN;
}
/* Copy the info bits. Clear the delete-mark. */
......@@ -3021,15 +3049,21 @@ updated_in_place:
lock_rec_store_on_page_infimum(page, rec);
page_cur_delete_rec(&page_cur, index, offsets, mtr);
page_cur_move_to_prev(&page_cur);
mem_heap_free(heap);
ibuf_insert_to_index_page_low(entry, page, index, mtr,
rec = ibuf_insert_to_index_page_low(entry, page, index, mtr,
&page_cur);
ut_ad(!cmp_dtuple_rec(entry, rec,
rec_get_offsets(rec, index, NULL,
ULINT_UNDEFINED,
&heap)));
mem_heap_free(heap);
lock_rec_restore_from_page_infimum(rec, page);
} else {
ibuf_insert_to_index_page_low(entry, page, index, mtr,
&page_cur);
}
DBUG_VOID_RETURN;
}
/*************************************************************************
......
/*****************************************************************************
Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -56,6 +56,7 @@ Created 7/19/1997 Heikki Tuuri
#include "lock0lock.h"
#include "log0recv.h"
#include "que0que.h"
#include "rem0cmp.h"
/* STRUCTURE OF AN INSERT BUFFER RECORD
......@@ -2890,11 +2891,13 @@ do_insert:
/********************************************************************//**
During merge, inserts to an index page a secondary index entry extracted
from the insert buffer. */
from the insert buffer.
@return newly inserted record */
static
void
rec_t*
ibuf_insert_to_index_page_low(
/*==========================*/
/* out: newly inserted record */
const dtuple_t* entry, /*!< in: buffered entry to insert */
buf_block_t* block, /*!< in/out: index page where the buffered
entry should be placed */
......@@ -2909,10 +2912,12 @@ ibuf_insert_to_index_page_low(
ulint zip_size;
const page_t* bitmap_page;
ulint old_bits;
rec_t* rec;
DBUG_ENTER("ibuf_insert_to_index_page_low");
if (UNIV_LIKELY
(page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) {
return;
rec = page_cur_tuple_insert(page_cur, entry, index, 0, mtr);
if (rec != NULL) {
DBUG_RETURN(rec);
}
/* If the record did not fit, reorganize */
......@@ -2922,9 +2927,9 @@ ibuf_insert_to_index_page_low(
/* This time the record must fit */
if (UNIV_LIKELY
(page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) {
return;
rec = page_cur_tuple_insert(page_cur, entry, index, 0, mtr);
if (rec != NULL) {
DBUG_RETURN(rec);
}
page = buf_block_get_frame(block);
......@@ -2957,6 +2962,7 @@ ibuf_insert_to_index_page_low(
fputs("InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
DBUG_RETURN(NULL);
}
/************************************************************************
......@@ -2976,6 +2982,7 @@ ibuf_insert_to_index_page(
ulint low_match;
page_t* page = buf_block_get_frame(block);
rec_t* rec;
DBUG_ENTER("ibuf_insert_to_index_page");
ut_ad(ibuf_inside());
ut_ad(dtuple_check_typed(entry));
......@@ -3011,7 +3018,7 @@ dump:
"InnoDB: Submit a detailed bug report to"
" http://bugs.mysql.com!\n", stderr);
return;
DBUG_VOID_RETURN;
}
low_match = page_cur_search(block, index, entry,
......@@ -3046,7 +3053,7 @@ dump:
rec, page_zip, FALSE, mtr);
updated_in_place:
mem_heap_free(heap);
return;
DBUG_VOID_RETURN;
}
/* Copy the info bits. Clear the delete-mark. */
......@@ -3090,15 +3097,21 @@ updated_in_place:
lock_rec_store_on_page_infimum(block, rec);
page_cur_delete_rec(&page_cur, index, offsets, mtr);
page_cur_move_to_prev(&page_cur);
mem_heap_free(heap);
ibuf_insert_to_index_page_low(entry, block, index, mtr,
rec = ibuf_insert_to_index_page_low(entry, block, index, mtr,
&page_cur);
ut_ad(!cmp_dtuple_rec(entry, rec,
rec_get_offsets(rec, index, NULL,
ULINT_UNDEFINED,
&heap)));
mem_heap_free(heap);
lock_rec_restore_from_page_infimum(block, rec, block);
} else {
ibuf_insert_to_index_page_low(entry, block, index, mtr,
&page_cur);
}
DBUG_VOID_RETURN;
}
/*********************************************************************//**
......
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