Commit a18ca211 authored by marko's avatar marko

branches/innodb+: ibuf0ibuf.c: Revert the patches to Issue #82

(r2962, r2865, r2864) and do not refuse to buffer deletes.  The
problem with refusing to buffer deletes was that no deletes were
buffered.

Instead, when merging delete requests, disregard a delete request
if it would make the page empty.  InnoDB tolerates redundant secondary
index records, but not empty pages.

ibuf_delete(): When merging a delete request, print and ignore the record
if the page would become empty.
parent 36c9bbc7
......@@ -2526,114 +2526,6 @@ ibuf_contract_after_insert(
}
}
/*************************************************************************
Determine if an insert buffer record has been encountered already. */
static
ibool
ibuf_get_volume_buffered_hash(
/*==========================*/
/* out: TRUE if a new record,
FALSE if possible duplicate */
const rec_t* rec, /* in: ibuf record in post-4.1 format */
byte* hash, /* in/out: hash array */
ulint size) /* in: size of hash array, in bytes */
{
ulint len;
ulint fold;
const byte* types;
ulint types_len;
ulint bitmask;
types = rec_get_nth_field_old(rec, 3, &types_len);
len = ibuf_rec_get_size(rec, types, rec_get_n_fields_old(rec) - 4,
FALSE);
fold = ut_fold_binary(types + types_len, len);
hash += (fold / 8) % size;
bitmask = 1 << (fold % 8);
if (*hash & bitmask) {
return(FALSE);
}
/* We have not seen this record yet. Insert it. */
*hash |= bitmask;
return(TRUE);
}
/*************************************************************************
Update the estimate of the number of records on a page. */
static
void
ibuf_get_volume_buffered_count(
/*===========================*/
const rec_t* rec, /* in: insert buffer record */
byte* hash, /* in/out: hash array */
ulint size, /* in: size of hash array, in bytes */
ulint* n_recs) /* in/out: estimated number of records
on the page that rec points to */
{
ulint len;
const byte* field;
ibuf_op_t ibuf_op;
ut_ad(ibuf_inside());
ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field_old(rec, 1, &len);
if (UNIV_UNLIKELY(len > 1)) {
/* This is a < 4.1.x format record. Ignore it in the
count, because deletes cannot be buffered if there are
old-style records for the page. */
return;
}
field = rec_get_nth_field_old(rec, 3, &len);
switch (UNIV_EXPECT(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE,
IBUF_REC_INFO_SIZE)) {
default:
ut_error;
case 0:
case 1:
/* This record does not include an operation counter.
Ignore it in the count, because deletes cannot be
buffered if there are old-style records for the page. */
return;
case IBUF_REC_INFO_SIZE:
ibuf_op = (ibuf_op_t) field[IBUF_REC_OFFSET_TYPE];
break;
}
switch (ibuf_op) {
case IBUF_OP_INSERT:
/* Inserts can be done by
btr_cur_set_deleted_flag_for_ibuf(). Because
delete-mark and insert operations can be pointing to
the same records, we must not count duplicates. */
case IBUF_OP_DELETE_MARK:
/* There must be a record to delete-mark.
See if this record has been already buffered. */
if (ibuf_get_volume_buffered_hash(rec, hash, size)) {
(*n_recs)++;
}
break;
case IBUF_OP_DELETE:
/* A record will be removed from the page. */
if (*n_recs > 0) {
(*n_recs)--;
}
break;
default:
ut_error;
}
}
/*************************************************************************
Gets an upper limit for the combined size of entries buffered in the insert
buffer for a given page. */
......@@ -2653,8 +2545,6 @@ ibuf_get_volume_buffered(
or BTR_MODIFY_TREE */
ulint space, /* in: space id */
ulint page_no,/* in: page number of an index page */
ulint* n_recs, /* out: minimum number of records on the page
after the buffered changes have been applied */
mtr_t* mtr) /* in: mtr */
{
ulint volume;
......@@ -2664,7 +2554,6 @@ ibuf_get_volume_buffered(
page_t* prev_page;
ulint next_page_no;
page_t* next_page;
byte hash_bitmap[128]; /* bitmap of buffered records */
ut_a(trx_sys_multiple_tablespace_format);
......@@ -2675,7 +2564,6 @@ ibuf_get_volume_buffered(
pcur */
volume = 0;
*n_recs = 0;
rec = btr_pcur_get_rec(pcur);
page = page_align(rec);
......@@ -2752,8 +2640,6 @@ ibuf_get_volume_buffered(
}
count_later:
memset(hash_bitmap, 0, sizeof hash_bitmap);
rec = btr_pcur_get_rec(pcur);
if (!page_rec_is_supremum(rec)) {
......@@ -2774,9 +2660,6 @@ ibuf_get_volume_buffered(
volume += ibuf_rec_get_volume(rec);
ibuf_get_volume_buffered_count(
rec, hash_bitmap, sizeof hash_bitmap, n_recs);
rec = page_rec_get_next(rec);
}
......@@ -2824,9 +2707,6 @@ ibuf_get_volume_buffered(
volume += ibuf_rec_get_volume(rec);
ibuf_get_volume_buffered_count(
rec, hash_bitmap, sizeof hash_bitmap, n_recs);
rec = page_rec_get_next(rec);
}
}
......@@ -3109,7 +2989,6 @@ ibuf_insert_low(
dtuple_t* ibuf_entry;
mem_heap_t* heap;
ulint buffered;
ulint min_n_recs;
rec_t* ins_rec;
ibool old_bit_value;
page_t* bitmap_page;
......@@ -3215,16 +3094,7 @@ ibuf_insert_low(
/* Find out the volume of already buffered inserts for the same index
page */
buffered = ibuf_get_volume_buffered(&pcur, space, page_no,
&min_n_recs, &mtr);
if (op == IBUF_OP_DELETE && min_n_recs == 0) {
/* The page could become empty after the record is
deleted. Refuse to buffer the operation. */
err = DB_STRONG_FAIL;
goto function_exit;
}
buffered = ibuf_get_volume_buffered(&pcur, space, page_no, &mtr);
#ifdef UNIV_IBUF_COUNT_DEBUG
ut_a((buffered == 0) || ibuf_count_get(space, page_no));
......@@ -3642,6 +3512,15 @@ ibuf_delete(
offsets = rec_get_offsets(
rec, index, offsets, ULINT_UNDEFINED, &heap);
if (UNIV_UNLIKELY(page_get_n_recs(page) == 1)) {
/* Refuse to delete the last record. */
ut_print_timestamp(stderr);
fputs(" InnoDB: refusing to merge a buffered delete"
" that would make a page empty\n", stderr);
rec_print_new(stderr, rec, offsets);
goto func_exit;
}
lock_update_delete(block, rec);
if (!page_zip) {
......@@ -3663,6 +3542,7 @@ ibuf_delete(
ibuf_update_free_bits_low(block, max_ins_size, mtr);
}
func_exit:
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
......
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