Skip to content

Commit 5b62644

Browse files
committed
MDEV-31621 Remove ibuf_read_merge_pages() call from ibuf_insert_low()
When InnoDB attempts to buffer a change operation of a secondary index leaf page (to insert, delete-mark or remove a record) and the change buffer is too large, InnoDB used to trigger a change buffer merge that could affect any tables. This could lead to huge variance in system throughput and potentially unpredictable crashes, in case the change buffer was corrupted and a crash occurred while attempting to merge changes to a table that is not being accessed by the current SQL statement. ibuf_insert_low(): Simply return DB_STRONG_FAIL when the maximum size of the change buffer is exceeded. ibuf_contract_after_insert(): Remove. ibuf_get_merge_page_nos_func(): Remove a constant parameter. The function ibuf_contract() will be our only caller, during shutdown with innodb_fast_shutdown=0.
1 parent 46b79b8 commit 5b62644

File tree

1 file changed

+17
-112
lines changed

1 file changed

+17
-112
lines changed

storage/innobase/ibuf/ibuf0ibuf.cc

Lines changed: 17 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -243,21 +243,11 @@ mysql_mutex_t ibuf_mutex,
243243
ibuf_pessimistic_insert_mutex;
244244

245245
/** The area in pages from which contract looks for page numbers for merge */
246-
const ulint IBUF_MERGE_AREA = 8;
246+
constexpr ulint IBUF_MERGE_AREA = 8;
247247

248-
/** Inside the merge area, pages which have at most 1 per this number less
249-
buffered entries compared to maximum volume that can buffered for a single
250-
page are merged along with the page whose buffer became full */
251-
const ulint IBUF_MERGE_THRESHOLD = 4;
252-
253-
/** In ibuf_contract at most this number of pages is read to memory in one
254-
batch, in order to merge the entries for them in the insert buffer */
255-
const ulint IBUF_MAX_N_PAGES_MERGED = IBUF_MERGE_AREA;
256-
257-
/** If the combined size of the ibuf trees exceeds ibuf.max_size by
258-
this many pages, we start to contract it synchronous contract, but do
259-
not insert */
260-
const ulint IBUF_CONTRACT_DO_NOT_INSERT = 10;
248+
/** In ibuf_contract() at most this number of pages is read to memory in one
249+
batch, in order to merge the entries for them in the change buffer */
250+
constexpr ulint IBUF_MAX_N_PAGES_MERGED = IBUF_MERGE_AREA;
261251

262252
/* TODO: how to cope with drop table if there are records in the insert
263253
buffer for the indexes of the table? Is there actually any problem,
@@ -2004,11 +1994,11 @@ ibuf_free_excess_pages(void)
20041994
}
20051995

20061996
#ifdef UNIV_DEBUG
2007-
# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,pages,n_stored) \
2008-
ibuf_get_merge_page_nos_func(contract,rec,mtr,ids,pages,n_stored)
1997+
# define ibuf_get_merge_page_nos(rec,mtr,ids,pages,n_stored) \
1998+
ibuf_get_merge_page_nos_func(rec,mtr,ids,pages,n_stored)
20091999
#else /* UNIV_DEBUG */
2010-
# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,pages,n_stored) \
2011-
ibuf_get_merge_page_nos_func(contract,rec,ids,pages,n_stored)
2000+
# define ibuf_get_merge_page_nos(rec,mtr,ids,pages,n_stored) \
2001+
ibuf_get_merge_page_nos_func(rec,ids,pages,n_stored)
20122002
#endif /* UNIV_DEBUG */
20132003

20142004
/*********************************************************************//**
@@ -2019,10 +2009,6 @@ static
20192009
ulint
20202010
ibuf_get_merge_page_nos_func(
20212011
/*=========================*/
2022-
ibool contract,/*!< in: TRUE if this function is called to
2023-
contract the tree, FALSE if this is called
2024-
when a single page becomes full and we look
2025-
if it pays to read also nearby pages */
20262012
const rec_t* rec, /*!< in: insert buffer record */
20272013
#ifdef UNIV_DEBUG
20282014
mtr_t* mtr, /*!< in: mini-transaction holding rec */
@@ -2153,22 +2139,10 @@ ibuf_get_merge_page_nos_func(
21532139
|| rec_page_no != prev_page_no)
21542140
&& (prev_space_id != 0 || prev_page_no != 0)) {
21552141

2156-
if (contract
2157-
|| (prev_page_no == first_page_no
2158-
&& prev_space_id == first_space_id)
2159-
|| (volume_for_page
2160-
> ((IBUF_MERGE_THRESHOLD - 1)
2161-
* 4U << srv_page_size_shift
2162-
/ IBUF_PAGE_SIZE_PER_FREE_SPACE)
2163-
/ IBUF_MERGE_THRESHOLD)) {
2164-
2165-
space_ids[*n_stored] = prev_space_id;
2166-
page_nos[*n_stored] = prev_page_no;
2167-
2168-
(*n_stored)++;
2169-
2170-
sum_volumes += volume_for_page;
2171-
}
2142+
space_ids[*n_stored] = prev_space_id;
2143+
page_nos[*n_stored] = prev_page_no;
2144+
(*n_stored)++;
2145+
sum_volumes += volume_for_page;
21722146

21732147
if (rec_space_id != first_space_id
21742148
|| rec_page_no / IBUF_MERGE_AREA
@@ -2428,7 +2402,7 @@ static void ibuf_read_merge_pages(const uint32_t* space_ids,
24282402
@return a lower limit for the combined size in bytes of entries which
24292403
will be merged from ibuf trees to the pages read
24302404
@retval 0 if ibuf.empty */
2431-
ulint ibuf_contract()
2405+
ATTRIBUTE_COLD ulint ibuf_contract()
24322406
{
24332407
if (UNIV_UNLIKELY(!ibuf.index)) return 0;
24342408
mtr_t mtr;
@@ -2460,10 +2434,8 @@ ulint ibuf_contract()
24602434
}
24612435

24622436
ulint n_pages = 0;
2463-
sum_sizes = ibuf_get_merge_page_nos(TRUE,
2464-
btr_cur_get_rec(&cur), &mtr,
2465-
space_ids,
2466-
page_nos, &n_pages);
2437+
sum_sizes = ibuf_get_merge_page_nos(btr_cur_get_rec(&cur), &mtr,
2438+
space_ids, page_nos, &n_pages);
24672439
ibuf_mtr_commit(&mtr);
24682440

24692441
ibuf_read_merge_pages(space_ids, page_nos, n_pages);
@@ -2553,30 +2525,6 @@ ibuf_merge_space(
25532525
return(n_pages);
25542526
}
25552527

2556-
/*********************************************************************//**
2557-
Contract insert buffer trees after insert if they are too big. */
2558-
UNIV_INLINE
2559-
void
2560-
ibuf_contract_after_insert(
2561-
/*=======================*/
2562-
ulint entry_size) /*!< in: size of a record which was inserted
2563-
into an ibuf tree */
2564-
{
2565-
/* dirty comparison, to avoid contention on ibuf_mutex */
2566-
if (ibuf.size < ibuf.max_size) {
2567-
return;
2568-
}
2569-
2570-
/* Contract at least entry_size many bytes */
2571-
ulint sum_sizes = 0;
2572-
ulint size;
2573-
2574-
do {
2575-
size = ibuf_contract();
2576-
sum_sizes += size;
2577-
} while (size > 0 && sum_sizes < entry_size);
2578-
}
2579-
25802528
/** Determine if a change buffer record has been encountered already.
25812529
@param rec change buffer record in the MySQL 5.5 format
25822530
@param hash hash table of encountered records
@@ -3175,10 +3123,6 @@ ibuf_insert_low(
31753123
buf_block_t* block = NULL;
31763124
page_t* root;
31773125
dberr_t err;
3178-
ibool do_merge;
3179-
uint32_t space_ids[IBUF_MAX_N_PAGES_MERGED];
3180-
uint32_t page_nos[IBUF_MAX_N_PAGES_MERGED];
3181-
ulint n_stored;
31823126
mtr_t mtr;
31833127
mtr_t bitmap_mtr;
31843128

@@ -3189,28 +3133,9 @@ ibuf_insert_low(
31893133
ut_ad(page_id.space() == index->table->space_id);
31903134
ut_a(op < IBUF_OP_COUNT);
31913135

3192-
do_merge = FALSE;
3193-
31943136
/* Perform dirty comparison of ibuf.max_size and ibuf.size to
3195-
reduce ibuf_mutex contention. This should be OK; at worst we
3196-
are doing some excessive ibuf_contract() or occasionally
3197-
skipping an ibuf_contract(). */
3198-
const ulint max_size = ibuf.max_size;
3199-
3200-
if (max_size == 0) {
3201-
return(DB_STRONG_FAIL);
3202-
}
3203-
3204-
if (ibuf.size >= max_size + IBUF_CONTRACT_DO_NOT_INSERT) {
3205-
/* Insert buffer is now too big, contract it but do not try
3206-
to insert */
3207-
3208-
3209-
#ifdef UNIV_IBUF_DEBUG
3210-
fputs("Ibuf too big\n", stderr);
3211-
#endif
3212-
ibuf_contract();
3213-
3137+
reduce ibuf_mutex contention. */
3138+
if (ibuf.size >= ibuf.max_size) {
32143139
return(DB_STRONG_FAIL);
32153140
}
32163141

@@ -3262,17 +3187,6 @@ ibuf_insert_low(
32623187
ibuf_mtr_commit(&mtr);
32633188
ut_free(pcur.old_rec_buf);
32643189
mem_heap_free(heap);
3265-
3266-
if (err == DB_SUCCESS && mode == BTR_INSERT_TREE) {
3267-
ibuf_contract_after_insert(entry_size);
3268-
}
3269-
3270-
if (do_merge) {
3271-
#ifdef UNIV_IBUF_DEBUG
3272-
ut_a(n_stored <= IBUF_MAX_N_PAGES_MERGED);
3273-
#endif
3274-
ibuf_read_merge_pages(space_ids, page_nos, n_stored);
3275-
}
32763190
return err;
32773191
}
32783192

@@ -3362,15 +3276,6 @@ ibuf_insert_low(
33623276
bits)) {
33633277
/* Release the bitmap page latch early. */
33643278
ibuf_mtr_commit(&bitmap_mtr);
3365-
3366-
/* It may not fit */
3367-
do_merge = TRUE;
3368-
3369-
ibuf_get_merge_page_nos(FALSE,
3370-
btr_pcur_get_rec(&pcur), &mtr,
3371-
space_ids,
3372-
page_nos, &n_stored);
3373-
33743279
goto fail_exit;
33753280
}
33763281
}

0 commit comments

Comments
 (0)