mirror of
https://github.com/MariaDB/server.git
synced 2026-05-06 07:05:33 +02:00
Merge 10.5 into 10.6
This commit is contained in:
commit
101da87228
22 changed files with 647 additions and 455 deletions
|
|
@ -7090,7 +7090,7 @@ static void btr_blob_free(buf_block_t *block, bool all, mtr_t *mtr)
|
|||
mysql_mutex_lock(&buf_pool.mutex);
|
||||
|
||||
if (buf_page_t *bpage= buf_pool.page_hash_get_low(page_id, fold))
|
||||
if(!buf_LRU_free_page(bpage, all) && all && bpage->zip.data)
|
||||
if (!buf_LRU_free_page(bpage, all) && all && bpage->zip.data)
|
||||
/* Attempt to deallocate the redundant copy of the uncompressed page
|
||||
if the whole ROW_FORMAT=COMPRESSED block cannot be deallocted. */
|
||||
buf_LRU_free_page(bpage, false);
|
||||
|
|
|
|||
|
|
@ -1108,13 +1108,15 @@ inline const buf_block_t *buf_pool_t::chunk_t::not_freed() const
|
|||
break;
|
||||
}
|
||||
|
||||
const lsn_t lsn= block->page.oldest_modification();
|
||||
|
||||
if (fsp_is_system_temporary(block->page.id().space()))
|
||||
{
|
||||
ut_ad(block->page.oldest_modification() <= 1);
|
||||
ut_ad(lsn == 0 || lsn == 2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!block->page.ready_for_replace())
|
||||
if (lsn > 1 || !block->page.can_relocate())
|
||||
return block;
|
||||
|
||||
break;
|
||||
|
|
@ -1269,9 +1271,9 @@ void buf_pool_t::close()
|
|||
Only on aborted startup (with recovery) or with innodb_fast_shutdown=2
|
||||
we may discard changes. */
|
||||
ut_d(const lsn_t oldest= bpage->oldest_modification();)
|
||||
ut_ad(!oldest || srv_is_being_started ||
|
||||
srv_fast_shutdown == 2 ||
|
||||
(oldest == 1 && fsp_is_system_temporary(bpage->id().space())));
|
||||
ut_ad(fsp_is_system_temporary(bpage->id().space())
|
||||
? (oldest == 0 || oldest == 2)
|
||||
: oldest <= 1 || srv_is_being_started || srv_fast_shutdown == 2);
|
||||
|
||||
if (bpage->state() != BUF_BLOCK_FILE_PAGE)
|
||||
buf_page_free_descriptor(bpage);
|
||||
|
|
@ -1489,10 +1491,10 @@ inline bool buf_pool_t::withdraw_blocks()
|
|||
|
||||
/* reserve free_list length */
|
||||
if (UT_LIST_GET_LEN(withdraw) < withdraw_target) {
|
||||
buf_flush_lists(
|
||||
buf_flush_LRU(
|
||||
std::max<ulint>(withdraw_target
|
||||
- UT_LIST_GET_LEN(withdraw),
|
||||
srv_LRU_scan_depth), 0);
|
||||
srv_LRU_scan_depth));
|
||||
buf_flush_wait_batch_end_acquiring_mutex(true);
|
||||
}
|
||||
|
||||
|
|
@ -2970,8 +2972,10 @@ re_evict:
|
|||
|
||||
fix_block->fix();
|
||||
mysql_mutex_unlock(&buf_pool.mutex);
|
||||
buf_flush_lists(ULINT_UNDEFINED, LSN_MAX);
|
||||
buf_flush_list();
|
||||
buf_flush_wait_batch_end_acquiring_mutex(false);
|
||||
while (buf_flush_list_space(space));
|
||||
os_aio_wait_until_no_pending_writes();
|
||||
|
||||
if (fix_block->page.buf_fix_count() == 1
|
||||
&& !fix_block->page.oldest_modification()) {
|
||||
|
|
@ -4066,8 +4070,8 @@ void buf_pool_t::print()
|
|||
<< UT_LIST_GET_LEN(flush_list)
|
||||
<< ", n pending decompressions=" << n_pend_unzip
|
||||
<< ", n pending reads=" << n_pend_reads
|
||||
<< ", n pending flush LRU=" << n_flush_LRU
|
||||
<< " list=" << n_flush_list
|
||||
<< ", n pending flush LRU=" << n_flush_LRU_
|
||||
<< " list=" << n_flush_list_
|
||||
<< ", pages made young=" << stat.n_pages_made_young
|
||||
<< ", not young=" << stat.n_pages_not_made_young
|
||||
<< ", pages read=" << stat.n_pages_read
|
||||
|
|
@ -4166,7 +4170,6 @@ void buf_stats_get_pool_info(buf_pool_info_t *pool_info)
|
|||
double time_elapsed;
|
||||
|
||||
mysql_mutex_lock(&buf_pool.mutex);
|
||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||
|
||||
pool_info->pool_size = buf_pool.curr_size;
|
||||
|
||||
|
|
@ -4176,17 +4179,17 @@ void buf_stats_get_pool_info(buf_pool_info_t *pool_info)
|
|||
|
||||
pool_info->free_list_len = UT_LIST_GET_LEN(buf_pool.free);
|
||||
|
||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||
pool_info->flush_list_len = UT_LIST_GET_LEN(buf_pool.flush_list);
|
||||
|
||||
pool_info->n_pend_unzip = UT_LIST_GET_LEN(buf_pool.unzip_LRU);
|
||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||
|
||||
pool_info->n_pend_reads = buf_pool.n_pend_reads;
|
||||
|
||||
pool_info->n_pending_flush_lru = buf_pool.n_flush_LRU;
|
||||
pool_info->n_pending_flush_lru = buf_pool.n_flush_LRU_;
|
||||
|
||||
pool_info->n_pending_flush_list = buf_pool.n_flush_list;
|
||||
|
||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||
pool_info->n_pending_flush_list = buf_pool.n_flush_list_;
|
||||
|
||||
current_time = time(NULL);
|
||||
time_elapsed = 0.001 + difftime(current_time,
|
||||
|
|
|
|||
|
|
@ -669,6 +669,13 @@ void buf_dblwr_t::flush_buffered_writes_completed(const IORequest &request)
|
|||
ut_d(buf_dblwr_check_page_lsn(*bpage, static_cast<const byte*>(frame)));
|
||||
}
|
||||
|
||||
const lsn_t lsn= mach_read_from_8(my_assume_aligned<8>
|
||||
(FIL_PAGE_LSN +
|
||||
static_cast<const byte*>(frame)));
|
||||
ut_ad(lsn);
|
||||
ut_ad(lsn >= bpage->oldest_modification());
|
||||
if (lsn > log_sys.get_flushed_lsn())
|
||||
log_write_up_to(lsn, true);
|
||||
e.request.node->space->io(e.request, bpage->physical_offset(), e_size,
|
||||
frame, bpage);
|
||||
}
|
||||
|
|
@ -682,7 +689,6 @@ void buf_dblwr_t::flush_buffered_writes()
|
|||
{
|
||||
if (!is_initialised() || !srv_use_doublewrite_buf)
|
||||
{
|
||||
os_aio_wait_until_no_pending_writes();
|
||||
fil_flush_file_spaces();
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -108,7 +108,7 @@ uint buf_LRU_old_threshold_ms;
|
|||
|
||||
/** Remove bpage from buf_pool.LRU and buf_pool.page_hash.
|
||||
|
||||
If bpage->state() == BUF_BLOCK_ZIP_PAGE && !bpage->oldest_modification(),
|
||||
If bpage->state() == BUF_BLOCK_ZIP_PAGE && bpage->oldest_modification() <= 1,
|
||||
the object will be freed.
|
||||
|
||||
@param bpage buffer block
|
||||
|
|
@ -242,8 +242,8 @@ static bool buf_LRU_free_from_common_LRU_list(ulint limit)
|
|||
buf_pool.lru_scan_itr.set(prev);
|
||||
|
||||
const auto accessed = bpage->is_accessed();
|
||||
if (!bpage->oldest_modification()
|
||||
&& buf_LRU_free_page(bpage, true)) {
|
||||
|
||||
if (buf_LRU_free_page(bpage, true)) {
|
||||
if (!accessed) {
|
||||
/* Keep track of pages that are evicted without
|
||||
ever being accessed. This gives us a measure of
|
||||
|
|
@ -449,8 +449,8 @@ retry:
|
|||
#ifndef DBUG_OFF
|
||||
not_found:
|
||||
#endif
|
||||
buf_flush_wait_batch_end(true);
|
||||
mysql_mutex_unlock(&buf_pool.mutex);
|
||||
buf_flush_wait_batch_end_acquiring_mutex(true);
|
||||
|
||||
if (n_iterations > 20 && !buf_lru_free_blocks_error_printed
|
||||
&& srv_buf_pool_old_size == srv_buf_pool_size) {
|
||||
|
|
@ -487,7 +487,7 @@ not_found:
|
|||
involved (particularly in case of ROW_FORMAT=COMPRESSED pages). We
|
||||
can do that in a separate patch sometime in future. */
|
||||
|
||||
if (!buf_flush_lists(innodb_lru_flush_size, 0)) {
|
||||
if (!buf_flush_LRU(innodb_lru_flush_size)) {
|
||||
MONITOR_INC(MONITOR_LRU_SINGLE_FLUSH_FAILURE_COUNT);
|
||||
++flush_failures;
|
||||
}
|
||||
|
|
@ -801,20 +801,33 @@ bool buf_LRU_free_page(buf_page_t *bpage, bool zip)
|
|||
const ulint fold = id.fold();
|
||||
page_hash_latch* hash_lock = buf_pool.page_hash.lock_get(fold);
|
||||
hash_lock->write_lock();
|
||||
lsn_t oldest_modification = bpage->oldest_modification();
|
||||
|
||||
if (UNIV_UNLIKELY(!bpage->can_relocate())) {
|
||||
/* Do not free buffer fixed and I/O-fixed blocks. */
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (oldest_modification == 1) {
|
||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||
oldest_modification = bpage->oldest_modification();
|
||||
if (oldest_modification) {
|
||||
ut_ad(oldest_modification == 1);
|
||||
buf_pool.delete_from_flush_list(bpage);
|
||||
}
|
||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||
ut_ad(!bpage->oldest_modification());
|
||||
oldest_modification = 0;
|
||||
}
|
||||
|
||||
if (zip || !bpage->zip.data) {
|
||||
/* This would completely free the block. */
|
||||
/* Do not completely free dirty blocks. */
|
||||
|
||||
if (bpage->oldest_modification()) {
|
||||
if (oldest_modification) {
|
||||
goto func_exit;
|
||||
}
|
||||
} else if (bpage->oldest_modification()
|
||||
} else if (oldest_modification
|
||||
&& bpage->state() != BUF_BLOCK_FILE_PAGE) {
|
||||
func_exit:
|
||||
hash_lock->write_unlock();
|
||||
|
|
|
|||
|
|
@ -40,11 +40,6 @@ Created 1/8/1996 Heikki Tuuri
|
|||
#include "sql_table.h"
|
||||
#include <mysql/service_thd_mdl.h>
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
|
||||
/** Flag to control insert buffer debugging. */
|
||||
extern uint ibuf_debug;
|
||||
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
|
||||
|
||||
#include "btr0btr.h"
|
||||
#include "btr0cur.h"
|
||||
#include "btr0sea.h"
|
||||
|
|
|
|||
|
|
@ -1079,7 +1079,7 @@ func_exit:
|
|||
mtr.commit();
|
||||
|
||||
/* 4 - sync tablespace before publishing crypt data */
|
||||
while (buf_flush_dirty_pages(space->id));
|
||||
while (buf_flush_list_space(space));
|
||||
|
||||
/* 5 - publish crypt data */
|
||||
mysql_mutex_lock(&fil_crypt_threads_mutex);
|
||||
|
|
@ -1820,7 +1820,7 @@ fil_crypt_rotate_page(
|
|||
if (block->page.status == buf_page_t::FREED) {
|
||||
/* Do not modify freed pages to avoid an assertion
|
||||
failure on recovery.*/
|
||||
} else if (block->page.oldest_modification()) {
|
||||
} else if (block->page.oldest_modification() > 1) {
|
||||
/* Do not unnecessarily touch pages that are
|
||||
already dirty. */
|
||||
} else if (space->is_stopping()) {
|
||||
|
|
@ -1970,14 +1970,7 @@ fil_crypt_flush_space(
|
|||
if (end_lsn > 0 && !space->is_stopping()) {
|
||||
ulint sum_pages = 0;
|
||||
const ulonglong start = my_interval_timer();
|
||||
do {
|
||||
ulint n_dirty= buf_flush_dirty_pages(state->space->id);
|
||||
if (!n_dirty) {
|
||||
break;
|
||||
}
|
||||
sum_pages += n_dirty;
|
||||
} while (!space->is_stopping());
|
||||
|
||||
while (buf_flush_list_space(space, &sum_pages));
|
||||
if (sum_pages) {
|
||||
const ulonglong end = my_interval_timer();
|
||||
|
||||
|
|
|
|||
|
|
@ -1642,9 +1642,7 @@ void fil_close_tablespace(ulint id)
|
|||
can no longer read more pages of this tablespace to buf_pool.
|
||||
Thus we can clean the tablespace out of buf_pool
|
||||
completely and permanently. */
|
||||
while (buf_flush_dirty_pages(id));
|
||||
/* Ensure that all asynchronous IO is completed. */
|
||||
os_aio_wait_until_no_pending_writes();
|
||||
while (buf_flush_list_space(space));
|
||||
ut_ad(space->is_stopping());
|
||||
|
||||
/* If it is a delete then also delete any generated files, otherwise
|
||||
|
|
|
|||
|
|
@ -987,9 +987,9 @@ static SHOW_VAR innodb_status_variables[]= {
|
|||
SHOW_SIZE_T},
|
||||
{"os_log_written", &export_vars.innodb_os_log_written, SHOW_SIZE_T},
|
||||
{"page_size", &srv_page_size, SHOW_ULONG},
|
||||
{"pages_created", &export_vars.innodb_pages_created, SHOW_SIZE_T},
|
||||
{"pages_read", &export_vars.innodb_pages_read, SHOW_SIZE_T},
|
||||
{"pages_written", &export_vars.innodb_pages_written, SHOW_SIZE_T},
|
||||
{"pages_created", &buf_pool.stat.n_pages_created, SHOW_SIZE_T},
|
||||
{"pages_read", &buf_pool.stat.n_pages_read, SHOW_SIZE_T},
|
||||
{"pages_written", &buf_pool.stat.n_pages_written, SHOW_SIZE_T},
|
||||
{"row_lock_current_waits", &export_vars.innodb_row_lock_current_waits,
|
||||
SHOW_SIZE_T},
|
||||
{"row_lock_time", &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
|
||||
|
|
|
|||
|
|
@ -672,6 +672,16 @@ private:
|
|||
/** Count of how manyfold this block is currently bufferfixed. */
|
||||
Atomic_counter<uint32_t> buf_fix_count_;
|
||||
|
||||
/** log sequence number of the START of the log entry written of the
|
||||
oldest modification to this block which has not yet been written
|
||||
to the data file;
|
||||
|
||||
0 if no modifications are pending;
|
||||
1 if no modifications are pending, but the block is in buf_pool.flush_list;
|
||||
2 if modifications are pending, but the block is not in buf_pool.flush_list
|
||||
(because id().space() is the temporary tablespace). */
|
||||
Atomic_counter<lsn_t> oldest_modification_;
|
||||
|
||||
/** type of pending I/O operation; protected by buf_pool.mutex
|
||||
if in_LRU_list */
|
||||
Atomic_relaxed<buf_io_fix> io_fix_;
|
||||
|
|
@ -721,12 +731,6 @@ public:
|
|||
or if state() is BUF_BLOCK_MEMORY or BUF_BLOCK_REMOVE_HASH. */
|
||||
UT_LIST_NODE_T(buf_page_t) list;
|
||||
|
||||
private:
|
||||
/** log sequence number of the START of the log entry written of the
|
||||
oldest modification to this block which has not yet been written
|
||||
to the data file; 0 if no modifications are pending. */
|
||||
Atomic_counter<lsn_t> oldest_modification_;
|
||||
public:
|
||||
/** @name LRU replacement algorithm fields.
|
||||
Protected by buf_pool.mutex. */
|
||||
/* @{ */
|
||||
|
|
@ -841,12 +845,19 @@ public:
|
|||
inline void set_io_fix(buf_io_fix io_fix);
|
||||
inline void set_corrupt_id();
|
||||
|
||||
/** @return the oldest modification */
|
||||
/** @return the log sequence number of the oldest pending modification
|
||||
@retval 0 if the block is not in buf_pool.flush_list
|
||||
@retval 1 if the block is in buf_pool.flush_list but not modified
|
||||
@retval 2 if the block belongs to the temporary tablespace and
|
||||
has unwritten changes */
|
||||
lsn_t oldest_modification() const { return oldest_modification_; }
|
||||
/** Set oldest_modification when adding to buf_pool.flush_list */
|
||||
inline void set_oldest_modification(lsn_t lsn);
|
||||
/** Clear oldest_modification when removing from buf_pool.flush_list */
|
||||
inline void clear_oldest_modification();
|
||||
/** Note that a block is no longer dirty, while not removing
|
||||
it from buf_pool.flush_list */
|
||||
inline void clear_oldest_modification(bool temporary);
|
||||
|
||||
/** Notify that a page in a temporary tablespace has been modified. */
|
||||
void set_temp_modified()
|
||||
|
|
@ -854,7 +865,7 @@ public:
|
|||
ut_ad(fsp_is_system_temporary(id().space()));
|
||||
ut_ad(state() == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(!oldest_modification());
|
||||
oldest_modification_= 1;
|
||||
oldest_modification_= 2;
|
||||
}
|
||||
|
||||
/** Prepare to release a file page to buf_pool.free. */
|
||||
|
|
@ -1462,23 +1473,24 @@ public:
|
|||
inline buf_block_t *block_from_ahi(const byte *ptr) const;
|
||||
#endif /* BTR_CUR_HASH_ADAPT */
|
||||
|
||||
/** @return the block that was made dirty the longest time ago */
|
||||
const buf_page_t *get_oldest_modified() const
|
||||
{
|
||||
mysql_mutex_assert_owner(&flush_list_mutex);
|
||||
const buf_page_t *bpage= UT_LIST_GET_LAST(flush_list);
|
||||
ut_ad(!bpage || !fsp_is_system_temporary(bpage->id().space()));
|
||||
ut_ad(!bpage || bpage->oldest_modification());
|
||||
return bpage;
|
||||
}
|
||||
|
||||
/**
|
||||
@return the smallest oldest_modification lsn for any page
|
||||
@retval empty_lsn if all modified persistent pages have been flushed */
|
||||
lsn_t get_oldest_modification(lsn_t empty_lsn) const
|
||||
lsn_t get_oldest_modification(lsn_t empty_lsn)
|
||||
{
|
||||
const buf_page_t *bpage= get_oldest_modified();
|
||||
return bpage ? bpage->oldest_modification() : empty_lsn;
|
||||
mysql_mutex_assert_owner(&flush_list_mutex);
|
||||
while (buf_page_t *bpage= UT_LIST_GET_LAST(flush_list))
|
||||
{
|
||||
ut_ad(!fsp_is_system_temporary(bpage->id().space()));
|
||||
lsn_t lsn= bpage->oldest_modification();
|
||||
if (lsn != 1)
|
||||
{
|
||||
ut_ad(lsn > 2);
|
||||
return lsn;
|
||||
}
|
||||
delete_from_flush_list(bpage);
|
||||
}
|
||||
return empty_lsn;
|
||||
}
|
||||
|
||||
/** Determine if a buffer block was created by chunk_t::create().
|
||||
|
|
@ -1692,15 +1704,18 @@ public:
|
|||
|
||||
/** Buffer pool mutex */
|
||||
MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) mysql_mutex_t mutex;
|
||||
/** Number of pending LRU flush. */
|
||||
Atomic_counter<ulint> n_flush_LRU;
|
||||
/** Number of pending LRU flush; protected by mutex. */
|
||||
ulint n_flush_LRU_;
|
||||
/** broadcast when n_flush_LRU reaches 0; protected by mutex */
|
||||
pthread_cond_t done_flush_LRU;
|
||||
/** Number of pending flush_list flush. */
|
||||
Atomic_counter<ulint> n_flush_list;
|
||||
/** Number of pending flush_list flush; protected by mutex */
|
||||
ulint n_flush_list_;
|
||||
/** broadcast when n_flush_list reaches 0; protected by mutex */
|
||||
pthread_cond_t done_flush_list;
|
||||
|
||||
TPOOL_SUPPRESS_TSAN ulint n_flush_LRU() const { return n_flush_LRU_; }
|
||||
TPOOL_SUPPRESS_TSAN ulint n_flush_list() const { return n_flush_list_; }
|
||||
|
||||
/** @name General fields */
|
||||
/* @{ */
|
||||
ulint curr_pool_size; /*!< Current pool size in bytes */
|
||||
|
|
@ -1875,8 +1890,8 @@ public:
|
|||
last_activity_count= activity_count;
|
||||
}
|
||||
|
||||
// n_flush_LRU + n_flush_list is approximately COUNT(io_fix()==BUF_IO_WRITE)
|
||||
// in flush_list
|
||||
// n_flush_LRU() + n_flush_list()
|
||||
// is approximately COUNT(io_fix()==BUF_IO_WRITE) in flush_list
|
||||
|
||||
unsigned freed_page_clock;/*!< a sequence number used
|
||||
to count the number of buffer
|
||||
|
|
@ -1961,13 +1976,35 @@ public:
|
|||
/** @return whether any I/O is pending */
|
||||
bool any_io_pending() const
|
||||
{
|
||||
return n_pend_reads || n_flush_LRU || n_flush_list;
|
||||
return n_pend_reads || n_flush_LRU() || n_flush_list();
|
||||
}
|
||||
/** @return total amount of pending I/O */
|
||||
ulint io_pending() const
|
||||
{
|
||||
return n_pend_reads + n_flush_LRU + n_flush_list;
|
||||
return n_pend_reads + n_flush_LRU() + n_flush_list();
|
||||
}
|
||||
|
||||
private:
|
||||
/** Remove a block from the flush list. */
|
||||
inline void delete_from_flush_list_low(buf_page_t *bpage);
|
||||
/** Remove a block from flush_list.
|
||||
@param bpage buffer pool page
|
||||
@param clear whether to invoke buf_page_t::clear_oldest_modification() */
|
||||
void delete_from_flush_list(buf_page_t *bpage, bool clear);
|
||||
public:
|
||||
/** Remove a block from flush_list.
|
||||
@param bpage buffer pool page */
|
||||
void delete_from_flush_list(buf_page_t *bpage)
|
||||
{ delete_from_flush_list(bpage, true); }
|
||||
|
||||
/** Insert a modified block into the flush list.
|
||||
@param block modified block
|
||||
@param lsn start LSN of the mini-transaction that modified the block */
|
||||
void insert_into_flush_list(buf_block_t *block, lsn_t lsn);
|
||||
|
||||
/** Free a page whose underlying file page has been freed. */
|
||||
inline void release_freed_page(buf_page_t *bpage);
|
||||
|
||||
private:
|
||||
/** Temporary memory for page_compressed and encrypted I/O */
|
||||
struct io_buf_t
|
||||
|
|
@ -2080,7 +2117,7 @@ inline void buf_page_t::set_corrupt_id()
|
|||
switch (oldest_modification()) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
ut_ad(fsp_is_system_temporary(id().space()));
|
||||
ut_d(oldest_modification_= 0); /* for buf_LRU_block_free_non_file_page() */
|
||||
break;
|
||||
|
|
@ -2106,7 +2143,7 @@ inline void buf_page_t::set_corrupt_id()
|
|||
inline void buf_page_t::set_oldest_modification(lsn_t lsn)
|
||||
{
|
||||
mysql_mutex_assert_owner(&buf_pool.flush_list_mutex);
|
||||
ut_ad(!oldest_modification());
|
||||
ut_ad(oldest_modification() <= 1);
|
||||
oldest_modification_= lsn;
|
||||
}
|
||||
|
||||
|
|
@ -2121,13 +2158,27 @@ inline void buf_page_t::clear_oldest_modification()
|
|||
oldest_modification_= 0;
|
||||
}
|
||||
|
||||
/** Note that a block is no longer dirty, while not removing
|
||||
it from buf_pool.flush_list */
|
||||
inline void buf_page_t::clear_oldest_modification(bool temporary)
|
||||
{
|
||||
mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex);
|
||||
ut_ad(temporary == fsp_is_system_temporary(id().space()));
|
||||
ut_ad(io_fix_ == BUF_IO_WRITE);
|
||||
ut_ad(temporary ? oldest_modification() == 2 : oldest_modification() > 2);
|
||||
oldest_modification_= !temporary;
|
||||
}
|
||||
|
||||
/** @return whether the block is modified and ready for flushing */
|
||||
inline bool buf_page_t::ready_for_flush() const
|
||||
{
|
||||
mysql_mutex_assert_owner(&buf_pool.mutex);
|
||||
ut_ad(in_LRU_list);
|
||||
ut_a(in_file());
|
||||
return oldest_modification() && io_fix_ == BUF_IO_NONE;
|
||||
ut_ad(fsp_is_system_temporary(id().space())
|
||||
? oldest_modification() == 2
|
||||
: oldest_modification() > 2);
|
||||
return io_fix_ == BUF_IO_NONE;
|
||||
}
|
||||
|
||||
/** @return whether the block can be relocated in memory.
|
||||
|
|
@ -2204,7 +2255,7 @@ MEMORY: is not in free list, LRU list, or flush list, nor page
|
|||
hash table
|
||||
FILE_PAGE: space and offset are defined, is in page hash table
|
||||
if io_fix == BUF_IO_WRITE,
|
||||
buf_pool.n_flush_LRU > 0 || buf_pool.n_flush_list > 0
|
||||
buf_pool.n_flush_LRU() || buf_pool.n_flush_list()
|
||||
|
||||
(1) if buf_fix_count == 0, then
|
||||
is in LRU list, not in free list
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2014, 2020, MariaDB Corporation.
|
||||
Copyright (c) 2014, 2021, 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
|
||||
|
|
@ -56,12 +56,6 @@ the list as they age towards the tail of the LRU.
|
|||
@param id tablespace identifier */
|
||||
void buf_flush_remove_pages(ulint id);
|
||||
|
||||
/** Try to flush all the dirty pages that belong to a given tablespace.
|
||||
@param id tablespace identifier
|
||||
@return number dirty pages that there were for this tablespace */
|
||||
ulint buf_flush_dirty_pages(ulint id)
|
||||
MY_ATTRIBUTE((warn_unused_result));
|
||||
|
||||
/*******************************************************************//**
|
||||
Relocates a buffer control block on the flush_list.
|
||||
Note that it is assumed that the contents of bpage has already been
|
||||
|
|
@ -95,10 +89,23 @@ buf_flush_init_for_writing(
|
|||
|
||||
/** Write out dirty blocks from buf_pool.flush_list.
|
||||
@param max_n wished maximum mumber of blocks flushed
|
||||
@param lsn buf_pool.get_oldest_modification(LSN_MAX) target (0=LRU flush)
|
||||
@param lsn buf_pool.get_oldest_modification(LSN_MAX) target
|
||||
@return the number of processed pages
|
||||
@retval 0 if a batch of the same type (lsn==0 or lsn!=0) is already running */
|
||||
ulint buf_flush_lists(ulint max_n, lsn_t lsn);
|
||||
@retval 0 if a buf_pool.flush_list batch is already running */
|
||||
ulint buf_flush_list(ulint max_n= ULINT_UNDEFINED, lsn_t lsn= LSN_MAX);
|
||||
|
||||
/** Try to flush dirty pages that belong to a given tablespace.
|
||||
@param space tablespace
|
||||
@param n_flushed number of pages written
|
||||
@return whether the flush for some pages might not have been initiated */
|
||||
bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed= nullptr)
|
||||
MY_ATTRIBUTE((warn_unused_result));
|
||||
|
||||
/** Write out dirty blocks from buf_pool.LRU.
|
||||
@param max_n wished maximum mumber of blocks flushed
|
||||
@return the number of processed pages
|
||||
@retval 0 if a buf_pool.LRU batch is already running */
|
||||
ulint buf_flush_LRU(ulint max_n);
|
||||
|
||||
/** Wait until a flush batch ends.
|
||||
@param lru true=buf_pool.LRU; false=buf_pool.flush_list */
|
||||
|
|
@ -106,9 +113,10 @@ void buf_flush_wait_batch_end(bool lru);
|
|||
/** Wait until all persistent pages are flushed up to a limit.
|
||||
@param sync_lsn buf_pool.get_oldest_modification(LSN_MAX) to wait for */
|
||||
ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn);
|
||||
/** If innodb_flush_sync=ON, initiate a furious flush.
|
||||
@param lsn buf_pool.get_oldest_modification(LSN_MAX) target */
|
||||
void buf_flush_ahead(lsn_t lsn);
|
||||
/** Initiate more eager page flushing if the log checkpoint age is too old.
|
||||
@param lsn buf_pool.get_oldest_modification(LSN_MAX) target
|
||||
@param furious true=furious flushing, false=limit to innodb_io_capacity */
|
||||
ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious);
|
||||
|
||||
/********************************************************************//**
|
||||
This function should be called at a mini-transaction commit, if a page was
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2019, 2020, MariaDB Corporation.
|
||||
Copyright (c) 2019, 2021, 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
|
||||
|
|
@ -26,17 +26,7 @@ Created 11/5/1995 Heikki Tuuri
|
|||
|
||||
#include "assume_aligned.h"
|
||||
#include "buf0buf.h"
|
||||
#include "mtr0mtr.h"
|
||||
#include "srv0srv.h"
|
||||
#include "fsp0types.h"
|
||||
|
||||
/********************************************************************//**
|
||||
Inserts a modified block into the flush list. */
|
||||
void
|
||||
buf_flush_insert_into_flush_list(
|
||||
/*=============================*/
|
||||
buf_block_t* block, /*!< in/out: block which is modified */
|
||||
lsn_t lsn); /*!< in: oldest modification */
|
||||
|
||||
/********************************************************************//**
|
||||
This function should be called at a mini-transaction commit, if a page was
|
||||
|
|
@ -52,8 +42,7 @@ buf_flush_note_modification(
|
|||
lsn_t end_lsn) /*!< in: end lsn of the mtr that
|
||||
modified this block */
|
||||
{
|
||||
ut_ad(!srv_read_only_mode
|
||||
|| fsp_is_system_temporary(block->page.id().space()));
|
||||
ut_ad(!srv_read_only_mode);
|
||||
ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->page.buf_fix_count());
|
||||
ut_ad(mach_read_from_8(block->frame + FIL_PAGE_LSN) <= end_lsn);
|
||||
|
|
@ -65,12 +54,12 @@ buf_flush_note_modification(
|
|||
|
||||
const lsn_t oldest_modification = block->page.oldest_modification();
|
||||
|
||||
if (oldest_modification) {
|
||||
if (oldest_modification > 1) {
|
||||
ut_ad(oldest_modification <= start_lsn);
|
||||
} else if (!fsp_is_system_temporary(block->page.id().space())) {
|
||||
buf_flush_insert_into_flush_list(block, start_lsn);
|
||||
} else {
|
||||
} else if (fsp_is_system_temporary(block->page.id().space())) {
|
||||
block->page.set_temp_modified();
|
||||
} else {
|
||||
buf_pool.insert_into_flush_list(block, start_lsn);
|
||||
}
|
||||
|
||||
srv_stats.buf_pool_write_requests.inc();
|
||||
|
|
|
|||
|
|
@ -588,6 +588,17 @@ public:
|
|||
@return number of buffer count added by this mtr */
|
||||
uint32_t get_fix_count(const buf_block_t *block) const;
|
||||
|
||||
/** type of page flushing is needed during commit() */
|
||||
enum page_flush_ahead
|
||||
{
|
||||
/** no need to trigger page cleaner */
|
||||
PAGE_FLUSH_NO= 0,
|
||||
/** asynchronous flushing is needed */
|
||||
PAGE_FLUSH_ASYNC,
|
||||
/** furious flushing is needed */
|
||||
PAGE_FLUSH_SYNC
|
||||
};
|
||||
|
||||
private:
|
||||
/** Log a write of a byte string to a page.
|
||||
@param block buffer page
|
||||
|
|
@ -621,7 +632,7 @@ private:
|
|||
/** Append the redo log records to the redo log buffer.
|
||||
@param len number of bytes to write
|
||||
@return {start_lsn,flush_ahead} */
|
||||
inline std::pair<lsn_t,bool> finish_write(ulint len);
|
||||
inline std::pair<lsn_t,page_flush_ahead> finish_write(ulint len);
|
||||
|
||||
/** Release the resources */
|
||||
inline void release_resources();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2017, 2020, MariaDB Corporation.
|
||||
Copyright (c) 2017, 2021, 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
|
||||
|
|
@ -32,7 +32,7 @@ inline bool mtr_t::is_block_dirtied(const buf_block_t *block)
|
|||
{
|
||||
ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->page.buf_fix_count());
|
||||
return !block->page.oldest_modification();
|
||||
return block->page.oldest_modification() <= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1111,10 +1111,9 @@ void os_aio_free();
|
|||
@retval DB_IO_ERROR on I/O error */
|
||||
dberr_t os_aio(const IORequest &type, void *buf, os_offset_t offset, size_t n);
|
||||
|
||||
/** Waits until there are no pending writes in os_aio_write_array. There can
|
||||
be other, synchronous, pending writes. */
|
||||
void
|
||||
os_aio_wait_until_no_pending_writes();
|
||||
/** Wait until there are no pending asynchronous writes.
|
||||
Only used on FLUSH TABLES...FOR EXPORT. */
|
||||
void os_aio_wait_until_no_pending_writes();
|
||||
|
||||
/** Wait until all pending asynchronous reads have completed. */
|
||||
void os_aio_wait_until_no_pending_reads();
|
||||
|
|
|
|||
|
|
@ -756,9 +756,6 @@ struct export_var_t{
|
|||
ulint innodb_os_log_fsyncs; /*!< n_log_flushes */
|
||||
ulint innodb_os_log_pending_writes; /*!< srv_os_log_pending_writes */
|
||||
ulint innodb_os_log_pending_fsyncs; /*!< n_pending_log_flushes */
|
||||
ulint innodb_pages_created; /*!< buf_pool.stat.n_pages_created */
|
||||
ulint innodb_pages_read; /*!< buf_pool.stat.n_pages_read*/
|
||||
ulint innodb_pages_written; /*!< buf_pool.stat.n_pages_written */
|
||||
ulint innodb_row_lock_waits; /*!< srv_n_lock_wait_count */
|
||||
ulint innodb_row_lock_current_waits; /*!< srv_n_lock_wait_current_count */
|
||||
int64_t innodb_row_lock_time; /*!< srv_n_lock_wait_time
|
||||
|
|
|
|||
|
|
@ -404,12 +404,12 @@ void mtr_t::commit()
|
|||
{
|
||||
ut_ad(!srv_read_only_mode || m_log_mode == MTR_LOG_NO_REDO);
|
||||
|
||||
std::pair<lsn_t,bool> lsns;
|
||||
std::pair<lsn_t,page_flush_ahead> lsns;
|
||||
|
||||
if (const ulint len= prepare_write())
|
||||
lsns= finish_write(len);
|
||||
else
|
||||
lsns= { m_commit_lsn, false };
|
||||
lsns= { m_commit_lsn, PAGE_FLUSH_NO };
|
||||
|
||||
if (m_made_dirty)
|
||||
mysql_mutex_lock(&log_sys.flush_order_mutex);
|
||||
|
|
@ -449,8 +449,8 @@ void mtr_t::commit()
|
|||
|
||||
m_memo.for_each_block_in_reverse(CIterate<ReleaseLatches>());
|
||||
|
||||
if (lsns.second)
|
||||
buf_flush_ahead(m_commit_lsn);
|
||||
if (UNIV_UNLIKELY(lsns.second != PAGE_FLUSH_NO))
|
||||
buf_flush_ahead(m_commit_lsn, lsns.second == PAGE_FLUSH_SYNC);
|
||||
|
||||
if (m_made_dirty)
|
||||
srv_stats.log_write_requests.inc();
|
||||
|
|
@ -767,7 +767,7 @@ static void log_write_low(const void *str, size_t size)
|
|||
|
||||
/** Close the log at mini-transaction commit.
|
||||
@return whether buffer pool flushing is needed */
|
||||
static bool log_close(lsn_t lsn)
|
||||
static mtr_t::page_flush_ahead log_close(lsn_t lsn)
|
||||
{
|
||||
mysql_mutex_assert_owner(&log_sys.mutex);
|
||||
ut_ad(lsn == log_sys.get_lsn());
|
||||
|
|
@ -790,7 +790,9 @@ static bool log_close(lsn_t lsn)
|
|||
|
||||
const lsn_t checkpoint_age= lsn - log_sys.last_checkpoint_lsn;
|
||||
|
||||
if (UNIV_UNLIKELY(checkpoint_age >= log_sys.log_capacity))
|
||||
if (UNIV_UNLIKELY(checkpoint_age >= log_sys.log_capacity) &&
|
||||
/* silence message on create_log_file() after the log had been deleted */
|
||||
checkpoint_age != lsn)
|
||||
{
|
||||
time_t t= time(nullptr);
|
||||
if (!log_close_warned || difftime(t, log_close_warn_time) > 15)
|
||||
|
|
@ -799,15 +801,17 @@ static bool log_close(lsn_t lsn)
|
|||
log_close_warn_time= t;
|
||||
|
||||
ib::error() << "The age of the last checkpoint is " << checkpoint_age
|
||||
<< ", which exceeds the log capacity "
|
||||
<< log_sys.log_capacity << ".";
|
||||
<< ", which exceeds the log capacity "
|
||||
<< log_sys.log_capacity << ".";
|
||||
}
|
||||
}
|
||||
else if (UNIV_LIKELY(checkpoint_age <= log_sys.max_modified_age_async))
|
||||
return mtr_t::PAGE_FLUSH_NO;
|
||||
else if (UNIV_LIKELY(checkpoint_age <= log_sys.max_checkpoint_age))
|
||||
return false;
|
||||
return mtr_t::PAGE_FLUSH_ASYNC;
|
||||
|
||||
log_sys.set_check_flush_or_checkpoint();
|
||||
return true;
|
||||
return mtr_t::PAGE_FLUSH_SYNC;
|
||||
}
|
||||
|
||||
/** Write the block contents to the REDO log */
|
||||
|
|
@ -871,8 +875,8 @@ inline ulint mtr_t::prepare_write()
|
|||
|
||||
/** Append the redo log records to the redo log buffer.
|
||||
@param len number of bytes to write
|
||||
@return {start_lsn,flush_ahead_lsn} */
|
||||
inline std::pair<lsn_t,bool> mtr_t::finish_write(ulint len)
|
||||
@return {start_lsn,flush_ahead} */
|
||||
inline std::pair<lsn_t,mtr_t::page_flush_ahead> mtr_t::finish_write(ulint len)
|
||||
{
|
||||
ut_ad(m_log_mode == MTR_LOG_ALL);
|
||||
mysql_mutex_assert_owner(&log_sys.mutex);
|
||||
|
|
@ -888,19 +892,19 @@ inline std::pair<lsn_t,bool> mtr_t::finish_write(ulint len)
|
|||
m_commit_lsn = log_reserve_and_write_fast(front->begin(), len,
|
||||
&start_lsn);
|
||||
|
||||
if (m_commit_lsn) {
|
||||
return std::make_pair(start_lsn, false);
|
||||
if (!m_commit_lsn) {
|
||||
goto piecewise;
|
||||
}
|
||||
} else {
|
||||
piecewise:
|
||||
/* Open the database log for log_write_low */
|
||||
start_lsn = log_reserve_and_open(len);
|
||||
mtr_write_log write_log;
|
||||
m_log.for_each_block(write_log);
|
||||
m_commit_lsn = log_sys.get_lsn();
|
||||
}
|
||||
|
||||
/* Open the database log for log_write_low */
|
||||
start_lsn = log_reserve_and_open(len);
|
||||
|
||||
mtr_write_log write_log;
|
||||
m_log.for_each_block(write_log);
|
||||
m_commit_lsn = log_sys.get_lsn();
|
||||
bool flush = log_close(m_commit_lsn);
|
||||
DBUG_EXECUTE_IF("ib_log_flush_ahead", flush=true;);
|
||||
page_flush_ahead flush= log_close(m_commit_lsn);
|
||||
DBUG_EXECUTE_IF("ib_log_flush_ahead", flush = PAGE_FLUSH_SYNC;);
|
||||
|
||||
return std::make_pair(start_lsn, flush);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3775,8 +3775,8 @@ static void os_aio_wait_until_no_pending_writes_low()
|
|||
tpool::tpool_wait_end();
|
||||
}
|
||||
|
||||
/** Waits until there are no pending writes. There can
|
||||
be other, synchronous, pending writes. */
|
||||
/** Wait until there are no pending asynchronous writes.
|
||||
Only used on FLUSH TABLES...FOR EXPORT. */
|
||||
void os_aio_wait_until_no_pending_writes()
|
||||
{
|
||||
os_aio_wait_until_no_pending_writes_low();
|
||||
|
|
|
|||
|
|
@ -4213,7 +4213,17 @@ row_import_for_mysql(
|
|||
/* Ensure that all pages dirtied during the IMPORT make it to disk.
|
||||
The only dirty pages generated should be from the pessimistic purge
|
||||
of delete marked records that couldn't be purged in Phase I. */
|
||||
while (buf_flush_dirty_pages(prebuilt->table->space_id));
|
||||
while (buf_flush_list_space(prebuilt->table->space));
|
||||
|
||||
for (ulint count = 0; prebuilt->table->space->referenced(); count++) {
|
||||
/* Issue a warning every 10.24 seconds, starting after
|
||||
2.56 seconds */
|
||||
if ((count & 511) == 128) {
|
||||
ib::warn() << "Waiting for flush to complete on "
|
||||
<< prebuilt->table->name;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
}
|
||||
|
||||
ib::info() << "Phase IV - Flush complete";
|
||||
prebuilt->table->space->set_imported();
|
||||
|
|
|
|||
|
|
@ -536,7 +536,7 @@ row_quiesce_table_start(
|
|||
}
|
||||
}
|
||||
|
||||
while (buf_flush_dirty_pages(table->space_id)) {
|
||||
while (buf_flush_list_space(table->space)) {
|
||||
if (trx_is_interrupted(trx)) {
|
||||
goto aborted;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1092,12 +1092,6 @@ srv_export_innodb_status(void)
|
|||
|
||||
export_vars.innodb_log_writes = srv_stats.log_writes;
|
||||
|
||||
export_vars.innodb_pages_created = buf_pool.stat.n_pages_created;
|
||||
|
||||
export_vars.innodb_pages_read = buf_pool.stat.n_pages_read;
|
||||
|
||||
export_vars.innodb_pages_written = buf_pool.stat.n_pages_written;
|
||||
|
||||
mysql_mutex_lock(&lock_sys.wait_mutex);
|
||||
export_vars.innodb_row_lock_waits = lock_sys.get_wait_cumulative();
|
||||
|
||||
|
|
|
|||
|
|
@ -672,7 +672,7 @@ not_free:
|
|||
mini-transaction commit and the server was killed, then
|
||||
discarding the to-be-trimmed pages without flushing would
|
||||
break crash recovery. So, we cannot avoid the write. */
|
||||
while (buf_flush_dirty_pages(space.id));
|
||||
while (buf_flush_list_space(&space));
|
||||
|
||||
log_free_check();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue