Commit 30dc4287 authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.5 into 10.6

parents 4e0004ea 0c23e32d
...@@ -711,9 +711,11 @@ void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr, ...@@ -711,9 +711,11 @@ void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
fseg_header_t* seg_header = &root[blob || page_is_leaf(block->frame) fseg_header_t* seg_header = &root[blob || page_is_leaf(block->frame)
? PAGE_HEADER + PAGE_BTR_SEG_LEAF ? PAGE_HEADER + PAGE_BTR_SEG_LEAF
: PAGE_HEADER + PAGE_BTR_SEG_TOP]; : PAGE_HEADER + PAGE_BTR_SEG_TOP];
fseg_free_page(seg_header, fil_space_t* space= index->table->space;
index->table->space, id.page_no(), mtr, space_latched); const uint32_t page= id.page_no();
buf_page_free(id, mtr);
fseg_free_page(seg_header, space, page, mtr, space_latched);
buf_page_free(space, page, mtr);
/* The page was marked free in the allocation bitmap, but it /* The page was marked free in the allocation bitmap, but it
should remain exclusively latched until mtr_t::commit() or until it should remain exclusively latched until mtr_t::commit() or until it
......
...@@ -2473,45 +2473,45 @@ inline buf_page_t *buf_pool_t::watch_set(const page_id_t id, ...@@ -2473,45 +2473,45 @@ inline buf_page_t *buf_pool_t::watch_set(const page_id_t id,
return nullptr; return nullptr;
} }
/** Mark the page status as FREED for the given tablespace id and /** Mark the page status as FREED for the given tablespace and page number.
page number. If the page is not in the buffer pool then ignore it. @param[in,out] space tablespace
X-lock should be taken on the page before marking the page status @param[in] page page number
as FREED. It avoids the concurrent flushing of freed page.
Currently, this function only marks the page as FREED if it is
in buffer pool.
@param[in] page_id page id
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
void buf_page_free(const page_id_t page_id, mtr_t *mtr) void buf_page_free(fil_space_t *space, uint32_t page, mtr_t *mtr)
{ {
ut_ad(mtr); ut_ad(mtr);
ut_ad(mtr->is_active()); ut_ad(mtr->is_active());
buf_pool.stat.n_page_gets++;
if (srv_immediate_scrub_data_uncompressed
#if defined HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || defined _WIN32
|| space->is_compressed()
#endif
)
mtr->add_freed_offset(space, page);
buf_pool.stat.n_page_gets++;
const page_id_t page_id(space->id, page);
const ulint fold= page_id.fold(); const ulint fold= page_id.fold();
page_hash_latch *hash_lock= buf_pool.page_hash.lock<false>(fold); page_hash_latch *hash_lock= buf_pool.page_hash.lock<false>(fold);
buf_block_t *block= reinterpret_cast<buf_block_t*> if (buf_block_t *block= reinterpret_cast<buf_block_t*>
(buf_pool.page_hash_get_low(page_id, fold)); (buf_pool.page_hash_get_low(page_id, fold)))
/* TODO: try to all this part of mtr_t::free() */
if (srv_immediate_scrub_data_uncompressed || mtr->is_page_compressed())
mtr->add_freed_offset(page_id);
if (!block || block->page.state() != BUF_BLOCK_FILE_PAGE)
{ {
/* FIXME: if block!=NULL, convert to BUF_BLOCK_FILE_PAGE, if (block->page.state() != BUF_BLOCK_FILE_PAGE)
but avoid buf_zip_decompress() */ /* FIXME: convert, but avoid buf_zip_decompress() */;
hash_lock->read_unlock(); else
return; {
} buf_block_buf_fix_inc(block);
ut_ad(block->page.buf_fix_count());
hash_lock->read_unlock();
buf_block_buf_fix_inc(block); mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX);
ut_ad(block->page.buf_fix_count()); block->lock.x_lock();
mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX); block->page.status= buf_page_t::FREED;
block->lock.x_lock(); return;
}
}
block->page.status= buf_page_t::FREED;
hash_lock->read_unlock(); hash_lock->read_unlock();
} }
......
...@@ -1396,6 +1396,19 @@ static void fil_crypt_return_iops(rotate_thread_t *state, bool wake= true) ...@@ -1396,6 +1396,19 @@ static void fil_crypt_return_iops(rotate_thread_t *state, bool wake= true)
fil_crypt_update_total_stat(state); fil_crypt_update_total_stat(state);
} }
/** Acquire a tablespace reference.
@return whether a tablespace reference was successfully acquired */
inline bool fil_space_t::acquire_if_not_stopped()
{
mysql_mutex_assert_owner(&fil_system.mutex);
const uint32_t n= acquire_low();
if (UNIV_LIKELY(!(n & (STOPPING | CLOSING))))
return true;
if (UNIV_UNLIKELY(n & STOPPING))
return false;
return UNIV_LIKELY(!(n & CLOSING)) || prepare(true);
}
/** Return the next tablespace from rotation_list. /** Return the next tablespace from rotation_list.
@param space previous tablespace (NULL to start from the start) @param space previous tablespace (NULL to start from the start)
@param recheck whether the removal condition needs to be rechecked after @param recheck whether the removal condition needs to be rechecked after
...@@ -1444,7 +1457,7 @@ inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space, ...@@ -1444,7 +1457,7 @@ inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space,
do do
{ {
space= &*it; space= &*it;
if (space->acquire_if_not_stopped(true)) if (space->acquire_if_not_stopped())
return space; return space;
if (++it == end) if (++it == end)
return nullptr; return nullptr;
...@@ -2168,7 +2181,7 @@ static void fil_crypt_rotation_list_fill() ...@@ -2168,7 +2181,7 @@ static void fil_crypt_rotation_list_fill()
if (space->purpose != FIL_TYPE_TABLESPACE if (space->purpose != FIL_TYPE_TABLESPACE
|| space->is_in_rotation_list || space->is_in_rotation_list
|| UT_LIST_GET_LEN(space->chain) == 0 || UT_LIST_GET_LEN(space->chain) == 0
|| !space->acquire_if_not_stopped(true)) { || !space->acquire_if_not_stopped()) {
continue; continue;
} }
......
...@@ -2631,9 +2631,7 @@ fseg_free_extent( ...@@ -2631,9 +2631,7 @@ fseg_free_extent(
for (ulint i = 0; i < FSP_EXTENT_SIZE; i++) { for (ulint i = 0; i < FSP_EXTENT_SIZE; i++) {
if (!xdes_is_free(descr, i)) { if (!xdes_is_free(descr, i)) {
buf_page_free( buf_page_free(space, first_page_in_extent + 1, mtr);
page_id_t(space->id, first_page_in_extent + 1),
mtr);
} }
} }
} }
......
...@@ -1935,7 +1935,7 @@ ibuf_remove_free_page(void) ...@@ -1935,7 +1935,7 @@ ibuf_remove_free_page(void)
ibuf_bitmap_page_set_bits<IBUF_BITMAP_IBUF>( ibuf_bitmap_page_set_bits<IBUF_BITMAP_IBUF>(
bitmap_page, page_id, srv_page_size, false, &mtr); bitmap_page, page_id, srv_page_size, false, &mtr);
buf_page_free(page_id, &mtr); buf_page_free(fil_system.sys_space, page_no, &mtr);
ibuf_mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
} }
......
...@@ -332,11 +332,11 @@ buf_page_release_latch( ...@@ -332,11 +332,11 @@ buf_page_release_latch(
RW_NO_LATCH */ RW_NO_LATCH */
/** Move a block to the start of the LRU list. */ /** Move a block to the start of the LRU list. */
void buf_page_make_young(buf_page_t *bpage); void buf_page_make_young(buf_page_t *bpage);
/** Mark the page status as FREED for the given tablespace id and /** Mark the page status as FREED for the given tablespace and page number.
page number. If the page is not in buffer pool then ignore it. @param[in,out] space tablespace
@param[in] page_id page_id @param[in] page page number
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
void buf_page_free(const page_id_t page_id, mtr_t *mtr); void buf_page_free(fil_space_t *space, uint32_t page, mtr_t *mtr);
/********************************************************************//** /********************************************************************//**
Reads the freed_page_clock of a buffer block. Reads the freed_page_clock of a buffer block.
......
...@@ -527,8 +527,9 @@ struct fil_space_t final ...@@ -527,8 +527,9 @@ struct fil_space_t final
} }
public: public:
MY_ATTRIBUTE((warn_unused_result)) MY_ATTRIBUTE((warn_unused_result))
/** @return whether a tablespace reference was successfully acquired */ /** Acquire a tablespace reference.
inline bool acquire_if_not_stopped(bool have_mutex= false); @return whether a tablespace reference was successfully acquired */
inline bool acquire_if_not_stopped();
MY_ATTRIBUTE((warn_unused_result)) MY_ATTRIBUTE((warn_unused_result))
/** Acquire a tablespace reference for I/O. /** Acquire a tablespace reference for I/O.
...@@ -1475,17 +1476,6 @@ inline void fil_space_t::reacquire() ...@@ -1475,17 +1476,6 @@ inline void fil_space_t::reacquire()
#endif /* SAFE_MUTEX */ #endif /* SAFE_MUTEX */
} }
inline bool fil_space_t::acquire_if_not_stopped(bool have_mutex)
{
#ifdef SAFE_MUTEX
ut_ad(mysql_mutex_is_owner(&fil_system.mutex) == have_mutex);
#endif
const uint32_t n= acquire_low();
if (UNIV_LIKELY(!(n & (STOPPING | CLOSING))))
return true;
return UNIV_LIKELY(!(n & CLOSING)) || prepare(have_mutex);
}
/** Note that operations on the tablespace must stop or can resume */ /** Note that operations on the tablespace must stop or can resume */
inline void fil_space_t::set_stopping(bool stopping) inline void fil_space_t::set_stopping(bool stopping)
{ {
......
...@@ -511,16 +511,18 @@ inline void mtr_t::memcpy(const buf_block_t &b, void *dest, const void *str, ...@@ -511,16 +511,18 @@ inline void mtr_t::memcpy(const buf_block_t &b, void *dest, const void *str,
@param[in,out] b buffer page */ @param[in,out] b buffer page */
inline void mtr_t::init(buf_block_t *b) inline void mtr_t::init(buf_block_t *b)
{ {
if (UNIV_LIKELY_NULL(m_freed_pages)) const page_id_t id{b->page.id()};
ut_ad(is_named_space(id.space()));
ut_ad(!m_freed_pages == !m_freed_space);
if (UNIV_LIKELY_NULL(m_freed_space) &&
m_freed_space->id == id.space() &&
m_freed_pages->remove_if_exists(b->page.id().page_no()) &&
m_freed_pages->empty())
{ {
ut_ad(m_log_mode != MTR_LOG_ALL || delete m_freed_pages;
m_user_space_id == b->page.id().space()); m_freed_pages= nullptr;
if (m_freed_pages->remove_if_exists(b->page.id().page_no()) && m_freed_space= nullptr;
m_freed_pages->empty())
{
delete m_freed_pages;
m_freed_pages= nullptr;
}
} }
b->page.status= buf_page_t::INIT_ON_FLUSH; b->page.status= buf_page_t::INIT_ON_FLUSH;
...@@ -540,15 +542,11 @@ inline void mtr_t::init(buf_block_t *b) ...@@ -540,15 +542,11 @@ inline void mtr_t::init(buf_block_t *b)
@param[in] offset page offset to be freed */ @param[in] offset page offset to be freed */
inline void mtr_t::free(fil_space_t &space, uint32_t offset) inline void mtr_t::free(fil_space_t &space, uint32_t offset)
{ {
page_id_t freed_page_id(space.id, offset); ut_ad(is_named_space(&space));
if (m_log_mode == MTR_LOG_ALL) ut_ad(!m_freed_space || m_freed_space == &space);
m_log.close(log_write<FREE_PAGE>(freed_page_id, nullptr));
ut_ad(!m_user_space || m_user_space == &space); if (m_log_mode == MTR_LOG_ALL)
if (&space == fil_system.sys_space) m_log.close(log_write<FREE_PAGE>({space.id, offset}, nullptr));
freed_system_tablespace_page();
else
m_user_space= &space;
} }
/** Write an EXTENDED log record. /** Write an EXTENDED log record.
......
...@@ -306,25 +306,12 @@ struct mtr_t { ...@@ -306,25 +306,12 @@ struct mtr_t {
/** @return true if we are inside the change buffer code */ /** @return true if we are inside the change buffer code */
bool is_inside_ibuf() const { return m_inside_ibuf; } bool is_inside_ibuf() const { return m_inside_ibuf; }
/** Note that system tablespace page has been freed. */
void freed_system_tablespace_page() { m_freed_in_system_tablespace= true; }
/** Note that pages has been trimed */ /** Note that pages has been trimed */
void set_trim_pages() { m_trim_pages= true; } void set_trim_pages() { m_trim_pages= true; }
/** @return true if pages has been trimed */ /** @return true if pages has been trimed */
bool is_trim_pages() { return m_trim_pages; } bool is_trim_pages() { return m_trim_pages; }
/** @return whether a page_compressed table was modified */
bool is_page_compressed() const
{
#if defined(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE) || defined(_WIN32)
return m_user_space && m_user_space->is_compressed();
#else
return false;
#endif
}
/** Latch a buffer pool block. /** Latch a buffer pool block.
@param block block to be latched @param block block to be latched
@param rw_latch RW_S_LATCH, RW_SX_LATCH, RW_X_LATCH, RW_NO_LATCH */ @param rw_latch RW_S_LATCH, RW_SX_LATCH, RW_X_LATCH, RW_NO_LATCH */
...@@ -377,12 +364,6 @@ struct mtr_t { ...@@ -377,12 +364,6 @@ struct mtr_t {
/** @return the memo stack */ /** @return the memo stack */
mtr_buf_t* get_memo() { return &m_memo; } mtr_buf_t* get_memo() { return &m_memo; }
/** @return true if system tablespace page has been freed */
bool is_freed_system_tablespace_page()
{
return m_freed_in_system_tablespace;
}
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/** @return true if a record was added to the mini-transaction */ /** @return true if a record was added to the mini-transaction */
...@@ -588,12 +569,18 @@ struct mtr_t { ...@@ -588,12 +569,18 @@ struct mtr_t {
const char *new_path= nullptr); const char *new_path= nullptr);
/** Add freed page numbers to freed_pages */ /** Add freed page numbers to freed_pages */
void add_freed_offset(page_id_t id) void add_freed_offset(fil_space_t *space, uint32_t page)
{ {
ut_ad(m_user_space == NULL || id.space() == m_user_space->id); ut_ad(is_named_space(space));
if (!m_freed_pages) if (!m_freed_pages)
{
m_freed_pages= new range_set(); m_freed_pages= new range_set();
m_freed_pages->add_value(id.page_no()); ut_ad(!m_freed_space);
m_freed_space= space;
}
else
ut_ad(m_freed_space == space);
m_freed_pages->add_value(page);
} }
/** Determine the added buffer fix count of a block. /** Determine the added buffer fix count of a block.
...@@ -671,9 +658,6 @@ struct mtr_t { ...@@ -671,9 +658,6 @@ struct mtr_t {
to suppress some read-ahead operations, @see ibuf_inside() */ to suppress some read-ahead operations, @see ibuf_inside() */
uint16_t m_inside_ibuf:1; uint16_t m_inside_ibuf:1;
/** whether the page has been freed in system tablespace */
uint16_t m_freed_in_system_tablespace:1;
/** whether the pages has been trimmed */ /** whether the pages has been trimmed */
uint16_t m_trim_pages:1; uint16_t m_trim_pages:1;
...@@ -695,6 +679,8 @@ struct mtr_t { ...@@ -695,6 +679,8 @@ struct mtr_t {
/** LSN at commit time */ /** LSN at commit time */
lsn_t m_commit_lsn; lsn_t m_commit_lsn;
/** tablespace where pages have been freed */
fil_space_t *m_freed_space= nullptr;
/** set of freed page ids */ /** set of freed page ids */
range_set *m_freed_pages= nullptr; range_set *m_freed_pages= nullptr;
}; };
......
...@@ -355,8 +355,10 @@ struct ReleaseBlocks ...@@ -355,8 +355,10 @@ struct ReleaseBlocks
void mtr_t::start() void mtr_t::start()
{ {
ut_ad(!m_freed_pages); ut_ad(!m_freed_pages);
ut_ad(!m_freed_space);
MEM_UNDEFINED(this, sizeof *this); MEM_UNDEFINED(this, sizeof *this);
MEM_MAKE_DEFINED(&m_freed_pages, sizeof(m_freed_pages)); MEM_MAKE_DEFINED(&m_freed_space, sizeof m_freed_space);
MEM_MAKE_DEFINED(&m_freed_pages, sizeof m_freed_pages);
ut_d(m_start= true); ut_d(m_start= true);
ut_d(m_commit= false); ut_d(m_commit= false);
...@@ -374,7 +376,7 @@ void mtr_t::start() ...@@ -374,7 +376,7 @@ void mtr_t::start()
ut_d(m_user_space_id= TRX_SYS_SPACE); ut_d(m_user_space_id= TRX_SYS_SPACE);
m_user_space= nullptr; m_user_space= nullptr;
m_commit_lsn= 0; m_commit_lsn= 0;
m_freed_in_system_tablespace= m_trim_pages= false; m_trim_pages= false;
} }
/** Release the resources */ /** Release the resources */
...@@ -419,28 +421,23 @@ void mtr_t::commit() ...@@ -419,28 +421,23 @@ void mtr_t::commit()
if (m_freed_pages) if (m_freed_pages)
{ {
ut_ad(!m_freed_pages->empty()); ut_ad(!m_freed_pages->empty());
fil_space_t *freed_space= m_user_space; ut_ad(m_freed_space);
/* Get the freed tablespace in case of predefined tablespace */ ut_ad(m_freed_space->is_owner());
if (!freed_space) ut_ad(is_named_space(m_freed_space));
{
ut_ad(is_freed_system_tablespace_page());
freed_space= fil_system.sys_space;
}
ut_ad(freed_space->is_owner());
/* Update the last freed lsn */ /* Update the last freed lsn */
freed_space->update_last_freed_lsn(m_commit_lsn); m_freed_space->update_last_freed_lsn(m_commit_lsn);
if (!is_trim_pages()) if (!is_trim_pages())
for (const auto &range : *m_freed_pages) for (const auto &range : *m_freed_pages)
freed_space->add_free_range(range); m_freed_space->add_free_range(range);
else else
freed_space->clear_freed_ranges(); m_freed_space->clear_freed_ranges();
delete m_freed_pages; delete m_freed_pages;
m_freed_pages= nullptr; m_freed_pages= nullptr;
/* Reset of m_trim_pages and m_freed_in_system_tablespace /* mtr_t::start() will reset m_trim_pages */
happens in mtr_t::start() */
} }
else
ut_ad(!m_freed_space);
m_memo.for_each_block_in_reverse(CIterate<const ReleaseBlocks> m_memo.for_each_block_in_reverse(CIterate<const ReleaseBlocks>
(ReleaseBlocks(lsns.first, m_commit_lsn, (ReleaseBlocks(lsns.first, m_commit_lsn,
...@@ -477,8 +474,8 @@ void mtr_t::commit_files(lsn_t checkpoint_lsn) ...@@ -477,8 +474,8 @@ void mtr_t::commit_files(lsn_t checkpoint_lsn)
ut_ad(!m_made_dirty); ut_ad(!m_made_dirty);
ut_ad(m_memo.size() == 0); ut_ad(m_memo.size() == 0);
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
ut_ad(!m_freed_space);
ut_ad(!m_freed_pages); ut_ad(!m_freed_pages);
ut_ad(!m_freed_in_system_tablespace);
if (checkpoint_lsn) { if (checkpoint_lsn) {
byte* ptr = m_log.push<byte*>(SIZE_OF_FILE_CHECKPOINT); byte* ptr = m_log.push<byte*>(SIZE_OF_FILE_CHECKPOINT);
......
...@@ -622,7 +622,7 @@ trx_undo_free_page( ...@@ -622,7 +622,7 @@ trx_undo_free_page(
fseg_free_page(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER fseg_free_page(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER
+ header_block->frame, + header_block->frame,
rseg->space, page_no, mtr); rseg->space, page_no, mtr);
buf_page_free(page_id_t(space, page_no), mtr); buf_page_free(rseg->space, page_no, mtr);
const fil_addr_t last_addr = flst_get_last( const fil_addr_t last_addr = flst_get_last(
TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + header_block->frame); TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + header_block->frame);
......
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