Commit b737d09d authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-29905 Change buffer operations fail to check for log file overflow

Every operation that is going to write redo log is supposed to
invoke log_free_check() before acquiring any latches. If there
is a risk of log buffer overrun, a log checkpoint would be
triggered by that call.

ibuf_merge_space(), ibuf_merge_in_background(),
ibuf_delete_for_discarded_space(): Invoke log_free_check()
when the current thread is not holding any page latches.

Unfortunately, in lower-level code called from ibuf_insert()
or ibuf_merge_or_delete_for_page(), some page latches may be
held and a call to log_free_check() could hang.

ibuf_set_bitmap_for_bulk_load(): Use the caller's mini-transaction.
The caller should have invoked log_free_check() while not holding
any page latches.
parent 49a0ad69
......@@ -398,8 +398,9 @@ PageBulk::finish()
void PageBulk::commit(bool success)
{
finish();
if (success && !dict_index_is_clust(m_index) && page_is_leaf(m_page))
ibuf_set_bitmap_for_bulk_load(m_block, innobase_fill_factor == 100);
if (success && !m_index->is_clust() && page_is_leaf(m_page))
ibuf_set_bitmap_for_bulk_load(m_block, &m_mtr,
innobase_fill_factor == 100);
m_mtr.commit();
}
......
......@@ -1067,12 +1067,12 @@ bitmap page)
bitmap page if the page is not one of the fixed address ibuf pages, or NULL,
in which case a new transaction is created.
@return TRUE if level 2 or level 3 page */
ibool
bool
ibuf_page_low(
const page_id_t page_id,
const page_size_t& page_size,
#ifdef UNIV_DEBUG
ibool x_latch,
bool x_latch,
#endif /* UNIV_DEBUG */
const char* file,
unsigned line,
......@@ -1954,10 +1954,7 @@ ibuf_data_too_much_free(void)
Allocates a new page from the ibuf file segment and adds it to the free
list.
@return TRUE on success, FALSE if no space left */
static
ibool
ibuf_add_free_page(void)
/*====================*/
static bool ibuf_add_free_page()
{
mtr_t mtr;
page_t* header_page;
......@@ -1966,7 +1963,7 @@ ibuf_add_free_page(void)
page_t* root;
page_t* bitmap_page;
mtr_start(&mtr);
mtr.start();
/* Acquire the fsp latch before the ibuf header, obeying the latching
order */
mtr_x_lock_space(fil_system.sys_space, &mtr);
......@@ -1987,9 +1984,8 @@ ibuf_add_free_page(void)
&mtr);
if (block == NULL) {
mtr_commit(&mtr);
return(FALSE);
mtr.commit();
return false;
}
ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
......@@ -2023,8 +2019,7 @@ ibuf_add_free_page(void)
IBUF_BITMAP_IBUF, TRUE, &mtr);
ibuf_mtr_commit(&mtr);
return(TRUE);
return true;
}
/*********************************************************************//**
......@@ -2520,6 +2515,7 @@ ibuf_merge_space(
ut_ad(space < SRV_LOG_SPACE_FIRST_ID);
log_free_check();
ibuf_mtr_start(&mtr);
/* Position the cursor on the first matching record. */
......@@ -2675,6 +2671,8 @@ ibuf_merge_in_background(
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
while (sum_pages < n_pages) {
log_free_check();
ulint n_bytes;
n_bytes = ibuf_merge(&n_pag2, false);
......@@ -4729,6 +4727,7 @@ ibuf_delete_for_discarded_space(
memset(dops, 0, sizeof(dops));
loop:
log_free_check();
ibuf_mtr_start(&mtr);
/* Position pcur in the insert buffer at the first entry for the
......@@ -4886,9 +4885,6 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
}
mtr_start(&mtr);
mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
ibuf_enter(&mtr);
bitmap_page = ibuf_bitmap_get_map_page(
......@@ -4978,36 +4974,24 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
return(DB_SUCCESS);
}
/** Updates free bits and buffered bits for bulk loaded page.
@param[in] block index page
@param[in] reset flag if reset free val */
void
ibuf_set_bitmap_for_bulk_load(
buf_block_t* block,
bool reset)
void ibuf_set_bitmap_for_bulk_load(buf_block_t *block, mtr_t *mtr, bool reset)
{
page_t* bitmap_page;
mtr_t mtr;
ulint free_val;
ut_a(page_is_leaf(buf_block_get_frame(block)));
free_val = ibuf_index_page_calc_free(block);
mtr_start(&mtr);
mtr.set_named_space_id(block->page.id.space());
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
block->page.size, &mtr);
block->page.size, mtr);
free_val = reset ? 0 : ibuf_index_page_calc_free(block);
ibuf_bitmap_page_set_bits(
bitmap_page, block->page.id, block->page.size,
IBUF_BITMAP_FREE, free_val, &mtr);
IBUF_BITMAP_FREE, free_val, mtr);
ibuf_bitmap_page_set_bits(
bitmap_page, block->page.id, block->page.size,
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
mtr_commit(&mtr);
IBUF_BITMAP_BUFFERED, FALSE, mtr);
}
/*****************************************************************************
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, 2019, MariaDB Corporation.
Copyright (c) 2016, 2022, MariaDB Corporation.
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
......@@ -261,12 +261,12 @@ bitmap page)
bitmap page if the page is not one of the fixed address ibuf pages, or NULL,
in which case a new transaction is created.
@return TRUE if level 2 or level 3 page */
ibool
bool
ibuf_page_low(
const page_id_t page_id,
const page_size_t& page_size,
#ifdef UNIV_DEBUG
ibool x_latch,
bool x_latch,
#endif /* UNIV_DEBUG */
const char* file,
unsigned line,
......@@ -274,7 +274,6 @@ ibuf_page_low(
MY_ATTRIBUTE((warn_unused_result));
#ifdef UNIV_DEBUG
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
Must not be called when recv_no_ibuf_operations==true.
@param[in] page_id tablespace/page identifier
......@@ -284,7 +283,7 @@ Must not be called when recv_no_ibuf_operations==true.
# define ibuf_page(page_id, page_size, mtr) \
ibuf_page_low(page_id, page_size, TRUE, __FILE__, __LINE__, mtr)
#else /* UVIV_DEBUG */
#else /* UNIV_DEBUG */
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
Must not be called when recv_no_ibuf_operations==true.
......@@ -295,7 +294,7 @@ Must not be called when recv_no_ibuf_operations==true.
# define ibuf_page(page_id, page_size, mtr) \
ibuf_page_low(page_id, page_size, __FILE__, __LINE__, mtr)
#endif /* UVIV_DEBUG */
#endif /* UNIV_DEBUG */
/***********************************************************************//**
Frees excess pages from the ibuf free list. This function is called when an OS
thread calls fsp services to allocate a new file segment, or a new page to a
......@@ -418,13 +417,11 @@ ibuf_close(void);
dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Updates free bits and buffered bits for bulk loaded page.
@param[in] block index page
@param]in] reset flag if reset free val */
void
ibuf_set_bitmap_for_bulk_load(
buf_block_t* block,
bool reset);
/** Update free bits and buffered bits for bulk loaded page.
@param block secondary index leaf page
@param mtr mini-transaction
@param reset whether the page is full */
void ibuf_set_bitmap_for_bulk_load(buf_block_t *block, mtr_t *mtr, bool reset);
#define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO
#define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO
......
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