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