summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorAnnamalai Gurusami <annamalai.gurusami@oracle.com>2013-05-16 14:05:05 +0530
committerAnnamalai Gurusami <annamalai.gurusami@oracle.com>2013-05-16 14:05:05 +0530
commitc43ce72cdbf8c4b045570926bcdb8f65971aa0c7 (patch)
treeefc320b2aedbd4e7e2675c7b0efbc4eddf5195e9 /storage
parentf1341a1d88445999146f27983b43de5bd5626339 (diff)
downloadmariadb-git-c43ce72cdbf8c4b045570926bcdb8f65971aa0c7.tar.gz
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
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.c58
-rw-r--r--storage/innodb_plugin/ibuf/ibuf0ibuf.c39
2 files changed, 72 insertions, 25 deletions
diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
index e2b5bda44fd..2ba3d785194 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.c
+++ b/storage/innobase/ibuf/ibuf0ibuf.c
@@ -1,3 +1,21 @@
+/*****************************************************************************
+
+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,
- &page_cur);
+ 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;
}
/*************************************************************************
diff --git a/storage/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
index c1c72b04f69..e084a61d5d3 100644
--- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c
+++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-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);
+
+ 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);
- ibuf_insert_to_index_page_low(entry, block, index, mtr,
- &page_cur);
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;
}
/*********************************************************************//**