mirror of
https://github.com/MariaDB/server.git
synced 2025-01-21 06:22:28 +01:00
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.
This commit is contained in:
parent
d82c072263
commit
4115c90530
1 changed files with 11 additions and 131 deletions
142
ibuf/ibuf0ibuf.c
142
ibuf/ibuf0ibuf.c
|
@ -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 @@ count_later:
|
|||
|
||||
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 @@ count_later:
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue