mirror of
https://github.com/MariaDB/server.git
synced 2025-02-01 11:31:51 +01:00
branches/innodb+: Revert r2964 and r2963. The heuristics for disabling
delete buffering is not fundamentally flawed. It merely failed because of other bugs.
This commit is contained in:
parent
c39afbb9f1
commit
46ccc6a652
1 changed files with 131 additions and 13 deletions
144
ibuf/ibuf0ibuf.c
144
ibuf/ibuf0ibuf.c
|
@ -2526,6 +2526,114 @@ 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 inserts buffered for a
|
||||
given page. */
|
||||
|
@ -2545,6 +2653,8 @@ 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;
|
||||
|
@ -2554,6 +2664,7 @@ 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);
|
||||
|
||||
|
@ -2564,6 +2675,7 @@ ibuf_get_volume_buffered(
|
|||
pcur */
|
||||
|
||||
volume = 0;
|
||||
*n_recs = 0;
|
||||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
page = page_align(rec);
|
||||
|
@ -2640,6 +2752,8 @@ 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)) {
|
||||
|
@ -2660,6 +2774,9 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -2707,6 +2824,9 @@ 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);
|
||||
}
|
||||
}
|
||||
|
@ -2989,6 +3109,7 @@ 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;
|
||||
|
@ -3093,7 +3214,16 @@ 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, &mtr);
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
ut_a((buffered == 0) || ibuf_count_get(space, page_no));
|
||||
|
@ -3515,17 +3645,6 @@ 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);
|
||||
fprintf(stderr, " InnoDB: refusing a buffered delete"
|
||||
" that would empty space %lu page %lu\n",
|
||||
(ulong) buf_block_get_space(block),
|
||||
(ulong) buf_block_get_page_no(block));
|
||||
rec_print_new(stderr, rec, offsets);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
lock_update_delete(block, rec);
|
||||
|
||||
if (!page_zip) {
|
||||
|
@ -3547,7 +3666,6 @@ ibuf_delete(
|
|||
ibuf_update_free_bits_low(block, max_ins_size, mtr);
|
||||
}
|
||||
|
||||
func_exit:
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue