summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-03-05 11:45:28 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-03-05 16:21:31 +0200
commita4ab54d70f26f93944e56c8e4e731e1107fdfa6b (patch)
tree5da731b4d210c84a92f0ec62bc95a8870f528de9
parent555f955a163040528b24b2a901140e43d7bc580f (diff)
downloadmariadb-git-a4ab54d70f26f93944e56c8e4e731e1107fdfa6b.tar.gz
MDEV-14425 Cleanup: Use std::atomic for some log_sys members
Some fields were protected by log_sys.mutex, which adds quite some overhead for readers. Some readers were submitting dirty reads. log_t::lsn: Declare private and atomic. Add wrappers get_lsn() and set_lsn() that will use relaxed memory access. Many accesses to log_sys.lsn are still protected by log_sys.mutex; we avoid the mutex for some readers. log_t::flushed_to_disk_lsn: Declare private and atomic, and move to the same cache line with log_t::lsn. log_t::buf_free: Declare as size_t, and move to the same cache line with log_t::lsn. log_t::check_flush_or_checkpoint_: Declare private and atomic, and move to the same cache line with log_t::lsn. log_get_lsn(): Define as an alias of log_sys.get_lsn(). log_get_lsn_nowait(), log_peek_lsn(): Remove. log_get_flush_lsn(): Define as an alias of log_sys.get_flush_lsn(). log_t::initiate_write(): Replaces log_buffer_sync_in_background().
-rw-r--r--storage/innobase/btr/btr0bulk.cc2
-rw-r--r--storage/innobase/buf/buf0buf.cc5
-rw-r--r--storage/innobase/buf/buf0flu.cc9
-rw-r--r--storage/innobase/fil/fil0fil.cc6
-rw-r--r--storage/innobase/handler/ha_innodb.cc4
-rw-r--r--storage/innobase/include/fil0fil.h4
-rw-r--r--storage/innobase/include/log0log.h101
-rw-r--r--storage/innobase/include/log0log.ic71
-rw-r--r--storage/innobase/log/log0log.cc198
-rw-r--r--storage/innobase/log/log0recv.cc21
-rw-r--r--storage/innobase/mtr/mtr0mtr.cc4
-rw-r--r--storage/innobase/row/row0merge.cc5
-rw-r--r--storage/innobase/srv/srv0mon.cc6
-rw-r--r--storage/innobase/srv/srv0srv.cc24
-rw-r--r--storage/innobase/srv/srv0start.cc18
15 files changed, 168 insertions, 310 deletions
diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc
index 4d73a6a4ac2..aeeb5850713 100644
--- a/storage/innobase/btr/btr0bulk.cc
+++ b/storage/innobase/btr/btr0bulk.cc
@@ -951,7 +951,7 @@ BtrBulk::pageCommit(
/** Log free check */
inline void BtrBulk::logFreeCheck()
{
- if (log_sys.check_flush_or_checkpoint) {
+ if (log_sys.check_flush_or_checkpoint()) {
release();
log_free_check();
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 6e2c62a1e57..24aef3fed5e 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -746,14 +746,13 @@ static void buf_page_check_lsn(bool check_lsn, const byte* read_buf)
{
#ifndef UNIV_INNOCHECKSUM
if (check_lsn && recv_lsn_checks_on) {
- lsn_t current_lsn;
+ const lsn_t current_lsn = log_sys.get_lsn();
const lsn_t page_lsn
= mach_read_from_8(read_buf + FIL_PAGE_LSN);
/* Since we are going to reset the page LSN during the import
phase it makes no sense to spam the log with error messages. */
-
- if (log_peek_lsn(&current_lsn) && current_lsn < page_lsn) {
+ if (current_lsn < page_lsn) {
const ulint space_id = mach_read_from_4(
read_buf + FIL_PAGE_SPACE_ID);
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index d74b41b0e8e..25584e5e6e2 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -2273,14 +2273,7 @@ page_cleaner_flush_pages_recommendation(ulint last_pages_in)
ulint pct_for_lsn = 0;
ulint pct_total = 0;
- cur_lsn = log_get_lsn_nowait();
-
- /* log_get_lsn_nowait tries to get log_sys.mutex with
- mutex_enter_nowait, if this does not succeed function
- returns 0, do not use that value to update stats. */
- if (cur_lsn == 0) {
- return(0);
- }
+ cur_lsn = log_sys.get_lsn();
if (prev_lsn == 0) {
/* First time around. */
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 129f672255b..b946ae3ae91 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -4462,12 +4462,12 @@ fil_names_dirty(
{
ut_ad(log_mutex_own());
ut_ad(recv_recovery_is_on());
- ut_ad(log_sys.lsn != 0);
+ ut_ad(log_sys.get_lsn() != 0);
ut_ad(space->max_lsn == 0);
ut_d(fil_space_validate_for_mtr_commit(space));
UT_LIST_ADD_LAST(fil_system.named_spaces, space);
- space->max_lsn = log_sys.lsn;
+ space->max_lsn = log_sys.get_lsn();
}
/** Write FILE_MODIFY records when a non-predefined persistent
@@ -4478,7 +4478,7 @@ void fil_names_dirty_and_write(fil_space_t* space)
{
ut_ad(log_mutex_own());
ut_d(fil_space_validate_for_mtr_commit(space));
- ut_ad(space->max_lsn == log_sys.lsn);
+ ut_ad(space->max_lsn == log_sys.get_lsn());
UT_LIST_ADD_LAST(fil_system.named_spaces, space);
mtr_t mtr;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 6cd83d180ed..087962d4c5e 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -18608,12 +18608,12 @@ checkpoint_now_set(THD*, st_mysql_sys_var*, void*, const void* save)
while (log_sys.last_checkpoint_lsn
+ SIZE_OF_FILE_CHECKPOINT
- < log_sys.lsn) {
+ < log_sys.get_lsn()) {
log_make_checkpoint();
log_sys.log.flush_data_only();
}
- dberr_t err = fil_write_flushed_lsn(log_sys.lsn);
+ dberr_t err = fil_write_flushed_lsn(log_sys.get_lsn());
if (err != DB_SUCCESS) {
ib::warn() << "Checkpoint set failed " << err;
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index e34c563df9e..dcfca4a7514 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -1523,8 +1523,8 @@ inline bool fil_names_write_if_was_clean(fil_space_t* space)
}
const bool was_clean = space->max_lsn == 0;
- ut_ad(space->max_lsn <= log_sys.lsn);
- space->max_lsn = log_sys.lsn;
+ ut_ad(space->max_lsn <= log_sys.get_lsn());
+ space->max_lsn = log_sys.get_lsn();
if (was_clean) {
fil_names_dirty_and_write(space);
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index 5911855d90c..9b3d0f214b6 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.h
@@ -127,27 +127,11 @@ Closes the log.
lsn_t
log_close(void);
/*===========*/
-/************************************************************//**
-Gets the current lsn.
-@return current lsn */
-UNIV_INLINE
-lsn_t
-log_get_lsn(void);
-/*=============*/
-/************************************************************//**
-Gets the current lsn.
-@return current lsn */
-UNIV_INLINE
-lsn_t
-log_get_lsn_nowait(void);
-/*=============*/
-/************************************************************//**
-Gets the last lsn that is fully flushed to disk.
-@return last flushed lsn */
-UNIV_INLINE
-ib_uint64_t
-log_get_flush_lsn(void);
-/*=============*/
+/** Read the current LSN. */
+#define log_get_lsn() log_sys.get_lsn()
+
+/** Read the durable LSN */
+#define log_get_flush_lsn() log_sys.get_flushed_lsn()
/****************************************************************
Get log_sys::max_modified_age_async. It is OK to read the value without
@@ -184,15 +168,7 @@ also to be flushed to disk. */
void
log_buffer_flush_to_disk(
bool sync = true);
-/****************************************************************//**
-This functions writes the log buffer to the log file and if 'flush'
-is set it forces a flush of the log file as well. This is meant to be
-called from background master thread only as it does not wait for
-the write (+ possible flush) to finish. */
-void
-log_buffer_sync_in_background(
-/*==========================*/
- bool flush); /*<! in: flush the logs to disk */
+
/** Make a checkpoint. Note that this function does not flush dirty
blocks from the buffer pool: it only checks what is lsn of the oldest
modification in the pool, and writes information about the lsn in
@@ -323,13 +299,6 @@ void
log_print(
/*======*/
FILE* file); /*!< in: file where to print */
-/******************************************************//**
-Peeks the current lsn.
-@return TRUE if success, FALSE if could not get the log system mutex */
-ibool
-log_peek_lsn(
-/*=========*/
- lsn_t* lsn); /*!< out: if returns TRUE, current lsn is here */
/**********************************************************************//**
Refreshes the statistics used to print per-second averages. */
void
@@ -560,10 +529,21 @@ struct log_t{
/** The MariaDB 10.5 physical format (only with innodb_encrypt_log=ON) */
static constexpr uint32_t FORMAT_ENC_10_5 = FORMAT_10_5 | FORMAT_ENCRYPTED;
- MY_ALIGNED(CACHE_LINE_SIZE)
- lsn_t lsn; /*!< log sequence number */
- ulong buf_free; /*!< first free offset within the log
- buffer in use */
+private:
+ /** The log sequence number of the last change of durable InnoDB files */
+ alignas(CACHE_LINE_SIZE)
+ std::atomic<lsn_t> lsn;
+ /** the first guaranteed-durable log sequence number */
+ std::atomic<lsn_t> flushed_to_disk_lsn;
+public:
+ /** first free offset within the log buffer in use */
+ size_t buf_free;
+private:
+ /** set when there may be need to flush the log buffer, or
+ preflush buffer pool pages, or initiate a log checkpoint.
+ This must hold if lsn - last_checkpoint_lsn > max_checkpoint_age. */
+ std::atomic<bool> check_flush_or_checkpoint_;
+public:
MY_ALIGNED(CACHE_LINE_SIZE)
LogSysMutex mutex; /*!< mutex protecting the log */
@@ -589,19 +569,9 @@ struct log_t{
bool first_in_use; /*!< true if buf points to the first
half of the buffer, false
if the second half */
- ulong max_buf_free; /*!< recommended maximum value of
+ size_t max_buf_free; /*!< recommended maximum value of
buf_free for the buffer in use, after
which the buffer is flushed */
- bool check_flush_or_checkpoint;
- /*!< this is set when there may
- be need to flush the log buffer, or
- preflush buffer pool pages, or make
- a checkpoint; this MUST be TRUE when
- lsn - last_checkpoint_lsn >
- max_checkpoint_age; this flag is
- peeked at by log_free_check(), which
- does not reserve the log mutex */
-
/** Log file stuff. Protected by mutex or write_mutex. */
struct file {
/** format of the redo log: e.g., FORMAT_10_5 */
@@ -684,7 +654,7 @@ struct log_t{
/** The fields involved in the log buffer flush @{ */
- ulong buf_next_to_write;/*!< first offset in the log buffer
+ size_t buf_next_to_write;/*!< first offset in the log buffer
where the byte content may not exist
written to file, e.g., the start
offset of a log record catenated
@@ -694,9 +664,6 @@ struct log_t{
lsn_t write_lsn; /*!< last written lsn */
lsn_t current_flush_lsn;/*!< end lsn for the current running
write + flush operation */
- lsn_t flushed_to_disk_lsn;
- /*!< how far we have written the log
- AND flushed to disk */
std::atomic<size_t> pending_flushes; /*!< system calls in progress */
std::atomic<size_t> flushes; /*!< system calls counter */
@@ -768,6 +735,19 @@ public:
bool is_initialised() const { return m_initialised; }
+ lsn_t get_lsn() const { return lsn.load(std::memory_order_relaxed); }
+ void set_lsn(lsn_t lsn) { this->lsn.store(lsn, std::memory_order_relaxed); }
+
+ lsn_t get_flushed_lsn() const
+ { return flushed_to_disk_lsn.load(std::memory_order_relaxed); }
+ void set_flushed_lsn(lsn_t lsn)
+ { flushed_to_disk_lsn.store(lsn, std::memory_order_relaxed); }
+
+ bool check_flush_or_checkpoint() const
+ { return check_flush_or_checkpoint_.load(std::memory_order_relaxed); }
+ void set_check_flush_or_checkpoint(bool flag= true)
+ { check_flush_or_checkpoint_.store(flag, std::memory_order_relaxed); }
+
/** @return the log block header + trailer size */
unsigned framing_size() const
{
@@ -806,6 +786,15 @@ public:
/** Shut down the redo log subsystem. */
void close();
+
+ /** Initiate a write of the log buffer to the file if needed.
+ @param flush whether to initiate a durable write */
+ inline void initiate_write(bool flush)
+ {
+ const lsn_t lsn= get_lsn();
+ if (!flush || get_flushed_lsn() < lsn)
+ log_write_up_to(lsn, flush);
+ }
};
/** Redo log system */
diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic
index 1ef92b373a6..624b6cad95c 100644
--- a/storage/innobase/include/log0log.ic
+++ b/storage/innobase/include/log0log.ic
@@ -296,7 +296,8 @@ log_reserve_and_write_fast(
return(0);
}
- *start_lsn = log_sys.lsn;
+ lsn_t lsn = log_sys.get_lsn();
+ *start_lsn = lsn;
memcpy(log_sys.buf + log_sys.buf_free, str, len);
@@ -306,70 +307,14 @@ log_reserve_and_write_fast(
OS_FILE_LOG_BLOCK_SIZE)),
data_len);
- log_sys.buf_free += ulong(len);
+ log_sys.buf_free += len;
- ut_ad(log_sys.buf_free <= srv_log_buffer_size);
+ ut_ad(log_sys.buf_free <= size_t{srv_log_buffer_size});
- log_sys.lsn += len;
+ lsn += len;
+ log_sys.set_lsn(lsn);
- return(log_sys.lsn);
-}
-
-/************************************************************//**
-Gets the current lsn.
-@return current lsn */
-UNIV_INLINE
-lsn_t
-log_get_lsn(void)
-/*=============*/
-{
- lsn_t lsn;
-
- log_mutex_enter();
-
- lsn = log_sys.lsn;
-
- log_mutex_exit();
-
- return(lsn);
-}
-
-/************************************************************//**
-Gets the last lsn that is fully flushed to disk.
-@return last flushed lsn */
-UNIV_INLINE
-ib_uint64_t
-log_get_flush_lsn(void)
-{
- ib_uint64_t lsn;
-
- log_mutex_enter();
-
- lsn = log_sys.flushed_to_disk_lsn;
-
- log_mutex_exit();
-
- return(lsn);
-}
-
-/************************************************************//**
-Gets the current lsn with a trylock
-@return current lsn or 0 if false*/
-UNIV_INLINE
-lsn_t
-log_get_lsn_nowait(void)
-/*====================*/
-{
- lsn_t lsn=0;
-
- if (!mutex_enter_nowait(&(log_sys.mutex))) {
-
- lsn = log_sys.lsn;
-
- mutex_exit(&(log_sys.mutex));
- }
-
- return(lsn);
+ return lsn;
}
/****************************************************************
@@ -413,7 +358,7 @@ log_free_check(void)
sync_allowed_latches(latches,
latches + UT_ARR_SIZE(latches))));
- if (log_sys.check_flush_or_checkpoint) {
+ if (log_sys.check_flush_or_checkpoint()) {
log_check_margins();
}
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 86c2ddf8464..de6e51bd2ea 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -115,7 +115,7 @@ log_buf_pool_get_oldest_modification(void)
if (!lsn) {
- lsn = log_sys.lsn;
+ lsn = log_sys.get_lsn();
}
return(lsn);
@@ -125,7 +125,7 @@ log_buf_pool_get_oldest_modification(void)
@param[in] len requested minimum size in bytes */
void log_buffer_extend(ulong len)
{
- const ulong new_buf_size = ut_calc_align(len, srv_page_size);
+ const size_t new_buf_size = ut_calc_align(len, srv_page_size);
byte* new_buf = static_cast<byte*>(
ut_malloc_dontdump(new_buf_size * 2));
TRASH_ALLOC(new_buf, new_buf_size * 2);
@@ -147,7 +147,7 @@ void log_buffer_extend(ulong len)
const ulong old_buf_size = srv_log_buffer_size;
byte* old_buf = log_sys.first_in_use
? log_sys.buf : log_sys.buf - old_buf_size;
- srv_log_buffer_size = new_buf_size;
+ srv_log_buffer_size = static_cast<ulong>(new_buf_size);
log_sys.buf = new_buf;
log_sys.first_in_use = true;
memcpy_aligned<OS_FILE_LOG_BLOCK_SIZE>(log_sys.buf, old_buf_begin,
@@ -225,20 +225,18 @@ log_margin_checkpoint_age(
/* Our margin check should ensure that we never reach this condition.
Try to do checkpoint once. We cannot keep waiting here as it might
result in hang in case the current mtr has latch on oldest lsn */
- if (log_sys.lsn - log_sys.last_checkpoint_lsn + margin
+ const lsn_t lsn = log_sys.get_lsn();
+
+ if (lsn - log_sys.last_checkpoint_lsn + margin
> log_sys.log_capacity) {
/* The log write of 'len' might overwrite the transaction log
after the last checkpoint. Makes checkpoint. */
- bool flushed_enough = false;
-
- if (log_sys.lsn - log_buf_pool_get_oldest_modification()
- + margin
- <= log_sys.log_capacity) {
- flushed_enough = true;
- }
+ const bool flushed_enough = lsn
+ - log_buf_pool_get_oldest_modification() + margin
+ <= log_sys.log_capacity;
- log_sys.check_flush_or_checkpoint = true;
+ log_sys.set_check_flush_or_checkpoint();
log_mutex_exit();
DEBUG_SYNC_C("margin_checkpoint_age_rescue");
@@ -281,7 +279,7 @@ loop:
DEBUG_SYNC_C("log_buf_size_exceeded");
/* Not enough free space, do a write of the log buffer */
- log_buffer_sync_in_background(false);
+ log_sys.initiate_write(false);
srv_stats.log_waits.inc();
@@ -291,7 +289,7 @@ loop:
goto loop;
}
- return(log_sys.lsn);
+ return(log_sys.get_lsn());
}
/************************************************************//**
@@ -334,6 +332,7 @@ part_loop:
OS_FILE_LOG_BLOCK_SIZE));
log_block_set_data_len(log_block, data_len);
+ lsn_t lsn = log_sys.get_lsn();
if (data_len == trailer_offset) {
/* This block became full */
@@ -342,18 +341,18 @@ part_loop:
log_sys.next_checkpoint_no);
len += log_sys.framing_size();
- log_sys.lsn += len;
+ lsn += len;
/* Initialize the next block header */
- log_block_init(log_block + OS_FILE_LOG_BLOCK_SIZE,
- log_sys.lsn);
+ log_block_init(log_block + OS_FILE_LOG_BLOCK_SIZE, lsn);
} else {
- log_sys.lsn += len;
+ lsn += len;
}
- log_sys.buf_free += ulong(len);
+ log_sys.set_lsn(lsn);
+ log_sys.buf_free += len;
- ut_ad(log_sys.buf_free <= srv_log_buffer_size);
+ ut_ad(log_sys.buf_free <= size_t{srv_log_buffer_size});
if (str_len > 0) {
goto part_loop;
@@ -377,7 +376,7 @@ log_close(void)
ut_ad(log_mutex_own());
- lsn = log_sys.lsn;
+ lsn = log_sys.get_lsn();
log_block = static_cast<byte*>(
ut_align_down(log_sys.buf + log_sys.buf_free,
@@ -395,7 +394,7 @@ log_close(void)
}
if (log_sys.buf_free > log_sys.max_buf_free) {
- log_sys.check_flush_or_checkpoint = true;
+ log_sys.set_check_flush_or_checkpoint();
}
checkpoint_age = lsn - log_sys.last_checkpoint_lsn;
@@ -418,7 +417,8 @@ log_close(void)
}
}
- if (checkpoint_age <= log_sys.max_modified_age_sync) {
+ if (checkpoint_age <= log_sys.max_modified_age_sync ||
+ log_sys.check_flush_or_checkpoint()) {
goto function_exit;
}
@@ -427,7 +427,7 @@ log_close(void)
if (!oldest_lsn
|| lsn - oldest_lsn > log_sys.max_modified_age_sync
|| checkpoint_age > log_sys.max_checkpoint_age_async) {
- log_sys.check_flush_or_checkpoint = true;
+ log_sys.set_check_flush_or_checkpoint();
}
function_exit:
@@ -502,7 +502,8 @@ void log_t::create()
/* Start the lsn from one log block from zero: this way every
log record has a non-zero start lsn, a fact which we will use */
- lsn= LOG_START_LSN;
+ set_lsn(LOG_START_LSN + LOG_BLOCK_HDR_SIZE);
+ set_flushed_lsn(0);
ut_ad(srv_log_buffer_size >= 16 * OS_FILE_LOG_BLOCK_SIZE);
ut_ad(srv_log_buffer_size >= 4U << srv_page_size_shift);
@@ -514,14 +515,13 @@ void log_t::create()
max_buf_free= srv_log_buffer_size / LOG_BUF_FLUSH_RATIO -
LOG_BUF_FLUSH_MARGIN;
- check_flush_or_checkpoint= true;
+ set_check_flush_or_checkpoint();
n_log_ios_old= n_log_ios;
last_printout_time= time(NULL);
buf_next_to_write= 0;
- write_lsn= lsn;
- flushed_to_disk_lsn= 0;
+ last_checkpoint_lsn= write_lsn= LOG_START_LSN;
n_log_ios= 0;
n_log_ios_old= 0;
log_capacity= 0;
@@ -533,13 +533,10 @@ void log_t::create()
next_checkpoint_lsn= 0;
n_pending_checkpoint_writes= 0;
- last_checkpoint_lsn= lsn;
-
- log_block_init(buf, lsn);
+ log_block_init(buf, LOG_START_LSN);
log_block_set_first_rec_group(buf, LOG_BLOCK_HDR_SIZE);
buf_free= LOG_BLOCK_HDR_SIZE;
- lsn= LOG_START_LSN + LOG_BLOCK_HDR_SIZE;
}
mapped_file_t::~mapped_file_t() noexcept
@@ -975,16 +972,11 @@ loop:
/** Flush the recently written changes to the log file.
and invoke log_mutex_enter(). */
-static
-void
-log_write_flush_to_disk_low(lsn_t lsn)
+static void log_write_flush_to_disk_low(lsn_t lsn)
{
- log_sys.log.flush_data_only();
-
- log_mutex_enter();
- ut_a(lsn >= log_sys.flushed_to_disk_lsn);
- log_sys.flushed_to_disk_lsn = lsn;
- log_mutex_exit();
+ log_sys.log.flush_data_only();
+ ut_a(lsn >= log_sys.get_flushed_lsn());
+ log_sys.set_flushed_lsn(lsn);
}
/** Switch the log buffer in use, and copy the content of last block
@@ -998,8 +990,8 @@ log_buffer_switch()
ut_ad(log_write_lock_own());
const byte* old_buf = log_sys.buf;
- ulong area_end = ut_calc_align(
- log_sys.buf_free, ulong(OS_FILE_LOG_BLOCK_SIZE));
+ size_t area_end = ut_calc_align<size_t>(
+ log_sys.buf_free, OS_FILE_LOG_BLOCK_SIZE);
if (log_sys.first_in_use) {
log_sys.first_in_use = false;
@@ -1052,7 +1044,7 @@ static void log_write(bool rotate_key)
DBUG_PRINT("ib_log", ("write " LSN_PF " to " LSN_PF,
log_sys.write_lsn,
- log_sys.lsn));
+ log_sys.get_lsn()));
start_offset = log_sys.buf_next_to_write;
@@ -1069,7 +1061,7 @@ static void log_write(bool rotate_key)
log_sys.buf + area_end - OS_FILE_LOG_BLOCK_SIZE,
log_sys.next_checkpoint_no);
- write_lsn = log_sys.lsn;
+ write_lsn = log_sys.get_lsn();
byte *write_buf = log_sys.buf;
log_buffer_switch();
@@ -1125,7 +1117,7 @@ static void log_write(bool rotate_key)
srv_stats.log_padded.add(pad_size);
log_sys.write_lsn = write_lsn;
if (log_sys.log.writes_are_durable())
- log_sys.flushed_to_disk_lsn = write_lsn;
+ log_sys.set_flushed_lsn(write_lsn);
return;
}
@@ -1168,7 +1160,7 @@ void log_write_up_to(lsn_t lsn, bool flush_to_disk, bool rotate_key)
if (write_lock.acquire(lsn) == group_commit_lock::ACQUIRED)
{
log_mutex_enter();
- auto write_lsn = log_sys.lsn;
+ lsn_t write_lsn= log_sys.get_lsn();
write_lock.set_pending(write_lsn);
log_write(rotate_key);
@@ -1207,34 +1199,6 @@ log_buffer_flush_to_disk(
log_write_up_to(log_get_lsn(), sync);
}
-/****************************************************************//**
-This functions writes the log buffer to the log file and if 'flush'
-is set it forces a flush of the log file as well. This is meant to be
-called from background master thread only as it does not wait for
-the write (+ possible flush) to finish. */
-void
-log_buffer_sync_in_background(
-/*==========================*/
- bool flush) /*!< in: flush the logs to disk */
-{
- lsn_t lsn;
-
- log_mutex_enter();
-
- lsn = log_sys.lsn;
-
- if (flush
- && log_sys.flushed_to_disk_lsn >= lsn) {
- /* The write + flush will write enough */
- log_mutex_exit();
- return;
- }
-
- log_mutex_exit();
-
- log_write_up_to(lsn, flush);
-}
-
/********************************************************************
Tries to establish a big enough margin of free space in the log buffer, such
@@ -1250,7 +1214,7 @@ log_flush_margin(void)
if (log_sys.buf_free > log_sys.max_buf_free) {
/* We can write during flush */
- lsn = log_sys.lsn;
+ lsn = log_sys.get_lsn();
}
log_mutex_exit();
@@ -1326,8 +1290,8 @@ void log_write_checkpoint_info(lsn_t end_lsn)
ut_ad(log_mutex_own());
ut_ad(!srv_read_only_mode);
ut_ad(end_lsn == 0 || end_lsn >= log_sys.next_checkpoint_lsn);
- ut_ad(end_lsn <= log_sys.lsn);
- ut_ad(end_lsn + SIZE_OF_FILE_CHECKPOINT <= log_sys.lsn
+ ut_ad(end_lsn <= log_sys.get_lsn());
+ ut_ad(end_lsn + SIZE_OF_FILE_CHECKPOINT <= log_sys.get_lsn()
|| srv_shutdown_state != SRV_SHUTDOWN_NONE);
DBUG_PRINT("ib_log", ("checkpoint " UINT64PF " at " LSN_PF
@@ -1384,7 +1348,7 @@ void log_write_checkpoint_info(lsn_t end_lsn)
DBUG_PRINT("ib_log", ("checkpoint ended at " LSN_PF
", flushed to " LSN_PF,
log_sys.last_checkpoint_lsn,
- log_sys.flushed_to_disk_lsn));
+ log_sys.get_flushed_lsn()));
MONITOR_INC(MONITOR_NUM_CHECKPOINT);
@@ -1467,14 +1431,14 @@ bool log_checkpoint()
threads will be blocked, and no pages can be added to the
flush lists. */
lsn_t flush_lsn = oldest_lsn;
- const lsn_t end_lsn = log_sys.lsn;
+ const lsn_t end_lsn = log_sys.get_lsn();
const bool do_write
= srv_shutdown_state == SRV_SHUTDOWN_NONE
|| flush_lsn != end_lsn;
if (fil_names_clear(flush_lsn, do_write)) {
- ut_ad(log_sys.lsn >= end_lsn + SIZE_OF_FILE_CHECKPOINT);
- flush_lsn = log_sys.lsn;
+ flush_lsn = log_sys.get_lsn();
+ ut_ad(flush_lsn >= end_lsn + SIZE_OF_FILE_CHECKPOINT);
}
log_mutex_exit();
@@ -1483,7 +1447,7 @@ bool log_checkpoint()
log_mutex_enter();
- ut_ad(log_sys.flushed_to_disk_lsn >= flush_lsn);
+ ut_ad(log_sys.get_flushed_lsn() >= flush_lsn);
ut_ad(flush_lsn >= oldest_lsn);
if (log_sys.last_checkpoint_lsn >= oldest_lsn) {
@@ -1529,10 +1493,7 @@ void
log_checkpoint_margin(void)
/*=======================*/
{
- lsn_t age;
- lsn_t checkpoint_age;
ib_uint64_t advance;
- lsn_t oldest_lsn;
bool success;
loop:
advance = 0;
@@ -1540,14 +1501,14 @@ loop:
log_mutex_enter();
ut_ad(!recv_no_log_write);
- if (!log_sys.check_flush_or_checkpoint) {
+ if (!log_sys.check_flush_or_checkpoint()) {
log_mutex_exit();
return;
}
- oldest_lsn = log_buf_pool_get_oldest_modification();
-
- age = log_sys.lsn - oldest_lsn;
+ const lsn_t oldest_lsn = log_buf_pool_get_oldest_modification();
+ const lsn_t lsn = log_sys.get_lsn();
+ const lsn_t age = lsn - oldest_lsn;
if (age > log_sys.max_modified_age_sync) {
@@ -1555,14 +1516,14 @@ loop:
advance = age - log_sys.max_modified_age_sync;
}
- checkpoint_age = log_sys.lsn - log_sys.last_checkpoint_lsn;
+ const lsn_t checkpoint_age = lsn - log_sys.last_checkpoint_lsn;
ut_ad(log_sys.max_checkpoint_age >= log_sys.max_checkpoint_age_async);
const bool do_checkpoint
= checkpoint_age > log_sys.max_checkpoint_age_async;
if (checkpoint_age <= log_sys.max_checkpoint_age) {
- log_sys.check_flush_or_checkpoint = false;
+ log_sys.set_check_flush_or_checkpoint(false);
}
log_mutex_exit();
@@ -1576,9 +1537,7 @@ loop:
and can proceed. If it did not succeed, there was another
thread doing a flush at the same time. */
if (!success) {
- log_mutex_enter();
- log_sys.check_flush_or_checkpoint = true;
- log_mutex_exit();
+ log_sys.set_check_flush_or_checkpoint();
goto loop;
}
}
@@ -1593,19 +1552,15 @@ Checks that there is enough free space in the log to start a new query step.
Flushes the log buffer or makes a new checkpoint if necessary. NOTE: this
function may only be called if the calling thread owns no synchronization
objects! */
-void
-log_check_margins(void)
+void log_check_margins()
{
- bool check;
-
- do {
- log_flush_margin();
- log_checkpoint_margin();
- log_mutex_enter();
- ut_ad(!recv_no_log_write);
- check = log_sys.check_flush_or_checkpoint;
- log_mutex_exit();
- } while (check);
+ do
+ {
+ log_flush_margin();
+ log_checkpoint_margin();
+ ut_ad(!recv_no_log_write);
+ }
+ while (log_sys.check_flush_or_checkpoint());
}
extern void buf_resize_shutdown();
@@ -1812,7 +1767,7 @@ wait_suspend_loop:
log_mutex_enter();
- lsn = log_sys.lsn;
+ lsn = log_sys.get_lsn();
const bool lsn_changed = lsn != log_sys.last_checkpoint_lsn
&& lsn != log_sys.last_checkpoint_lsn
@@ -1841,7 +1796,7 @@ wait_suspend_loop:
"Free innodb buffer pool");
ut_d(buf_assert_all_freed());
- ut_a(lsn == log_sys.lsn
+ ut_a(lsn == log_sys.get_lsn()
|| srv_force_recovery == SRV_FORCE_NO_LOG_REDO);
if (UNIV_UNLIKELY(lsn < recv_sys.recovered_lsn)) {
@@ -1866,30 +1821,11 @@ wait_suspend_loop:
/* Make some checks that the server really is quiet */
ut_ad(!srv_any_background_activity());
- ut_a(lsn == log_sys.lsn
+ ut_a(lsn == log_sys.get_lsn()
|| srv_force_recovery == SRV_FORCE_NO_LOG_REDO);
}
/******************************************************//**
-Peeks the current lsn.
-@return TRUE if success, FALSE if could not get the log system mutex */
-ibool
-log_peek_lsn(
-/*=========*/
- lsn_t* lsn) /*!< out: if returns TRUE, current lsn is here */
-{
- if (0 == mutex_enter_nowait(&(log_sys.mutex))) {
- *lsn = log_sys.lsn;
-
- log_mutex_exit();
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/******************************************************//**
Prints info of the log. */
void
log_print(
@@ -1906,8 +1842,8 @@ log_print(
"Log flushed up to " LSN_PF "\n"
"Pages flushed up to " LSN_PF "\n"
"Last checkpoint at " LSN_PF "\n",
- log_sys.lsn,
- log_sys.flushed_to_disk_lsn,
+ log_sys.get_lsn(),
+ log_sys.get_flushed_lsn(),
log_buf_pool_get_oldest_modification(),
log_sys.last_checkpoint_lsn);
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 3e31848e5e9..67783e0f891 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -1466,9 +1466,10 @@ static dberr_t recv_log_format_0_recover(lsn_t lsn, bool crypt)
= recv_sys.scanned_lsn
= recv_sys.mlog_checkpoint_lsn = lsn;
log_sys.last_checkpoint_lsn = log_sys.next_checkpoint_lsn
- = log_sys.lsn = log_sys.write_lsn
- = log_sys.current_flush_lsn = log_sys.flushed_to_disk_lsn
- = lsn;
+ = log_sys.write_lsn = log_sys.current_flush_lsn = lsn;
+ log_sys.set_lsn(lsn);
+ log_sys.set_flushed_lsn(lsn);
+
log_sys.next_checkpoint_no = 0;
recv_sys.remove_extra_log_files = true;
return(DB_SUCCESS);
@@ -1525,10 +1526,10 @@ static dberr_t recv_log_recover_10_4()
recv_sys.parse_start_lsn = recv_sys.recovered_lsn
= recv_sys.scanned_lsn
= recv_sys.mlog_checkpoint_lsn = lsn;
+ log_sys.set_lsn(lsn);
+ log_sys.set_flushed_lsn(lsn);
log_sys.last_checkpoint_lsn = log_sys.next_checkpoint_lsn
- = log_sys.lsn = log_sys.write_lsn
- = log_sys.current_flush_lsn = log_sys.flushed_to_disk_lsn
- = lsn;
+ = log_sys.write_lsn = log_sys.current_flush_lsn = lsn;
log_sys.next_checkpoint_no = 0;
recv_sys.remove_extra_log_files = true;
return DB_SUCCESS;
@@ -3298,7 +3299,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
if (err != DB_SUCCESS) {
- recv_sys.recovered_lsn = log_sys.lsn;
+ recv_sys.recovered_lsn = log_sys.get_lsn();
log_mutex_exit();
return(err);
}
@@ -3434,7 +3435,7 @@ completed:
}
}
- log_sys.lsn = recv_sys.recovered_lsn;
+ log_sys.set_lsn(recv_sys.recovered_lsn);
if (recv_needed_recovery) {
bool missing_tablespace = false;
@@ -3537,9 +3538,9 @@ completed:
ut_ad(recv_needed_recovery
|| checkpoint_lsn == recv_sys.recovered_lsn);
- log_sys.buf_free = ulong(log_sys.lsn % OS_FILE_LOG_BLOCK_SIZE);
+ log_sys.write_lsn = log_sys.get_lsn();
+ log_sys.buf_free = log_sys.write_lsn % OS_FILE_LOG_BLOCK_SIZE;
log_sys.buf_next_to_write = log_sys.buf_free;
- log_sys.write_lsn = log_sys.lsn;
log_sys.last_checkpoint_lsn = checkpoint_lsn;
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index 45c2ac68ef1..c058a93265c 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -459,7 +459,7 @@ void mtr_t::commit_files(lsn_t checkpoint_lsn)
if (checkpoint_lsn) {
DBUG_PRINT("ib_log",
("FILE_CHECKPOINT(" LSN_PF ") written at " LSN_PF,
- checkpoint_lsn, log_sys.lsn));
+ checkpoint_lsn, log_sys.get_lsn()));
}
}
@@ -589,7 +589,7 @@ inline ulint mtr_t::prepare_write()
ut_ad(m_log_mode == MTR_LOG_NO_REDO);
ut_ad(m_log.size() == 0);
log_mutex_enter();
- m_commit_lsn = log_sys.lsn;
+ m_commit_lsn = log_sys.get_lsn();
return 0;
}
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 5523b867bf5..42f38c5a1cc 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -125,8 +125,7 @@ public:
ut_ad(mtr_started == scan_mtr->is_active());
DBUG_EXECUTE_IF("row_merge_instrument_log_check_flush",
- log_sys.check_flush_or_checkpoint = true;
- );
+ log_sys.set_check_flush_or_checkpoint(););
for (idx_tuple_vec::iterator it = m_dtuple_vec->begin();
it != m_dtuple_vec->end();
@@ -134,7 +133,7 @@ public:
dtuple = *it;
ut_ad(dtuple);
- if (log_sys.check_flush_or_checkpoint) {
+ if (log_sys.check_flush_or_checkpoint()) {
if (mtr_started) {
btr_pcur_move_to_prev_on_page(pcur);
btr_pcur_store_position(pcur, scan_mtr);
diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc
index b4928c5d59b..f34680b9aed 100644
--- a/storage/innobase/srv/srv0mon.cc
+++ b/storage/innobase/srv/srv0mon.cc
@@ -1969,11 +1969,11 @@ srv_mon_process_existing_counter(
break;
case MONITOR_OVLD_LSN_FLUSHDISK:
- value = (mon_type_t) log_sys.flushed_to_disk_lsn;
+ value = log_sys.get_flushed_lsn();
break;
case MONITOR_OVLD_LSN_CURRENT:
- value = (mon_type_t) log_sys.lsn;
+ value = log_sys.get_lsn();
break;
case MONITOR_PENDING_LOG_FLUSH:
@@ -1996,7 +1996,7 @@ srv_mon_process_existing_counter(
case MONITOR_LSN_CHECKPOINT_AGE:
mutex_enter(&log_sys.mutex);
- value = static_cast<mon_type_t>(log_sys.lsn
+ value = static_cast<mon_type_t>(log_sys.get_lsn()
- log_sys.last_checkpoint_lsn);
mutex_exit(&log_sys.mutex);
break;
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 25b01daa2e0..ba765aa1a27 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1364,16 +1364,16 @@ srv_export_innodb_status(void)
mutex_exit(&srv_innodb_monitor_mutex);
log_mutex_enter();
-
- export_vars.innodb_lsn_current = log_sys.lsn;
- export_vars.innodb_lsn_flushed = log_sys.flushed_to_disk_lsn;
+ export_vars.innodb_lsn_current = log_sys.get_lsn();
+ export_vars.innodb_lsn_flushed = log_sys.get_flushed_lsn();
export_vars.innodb_lsn_last_checkpoint = log_sys.last_checkpoint_lsn;
- export_vars.innodb_checkpoint_age = static_cast<ulint>(
- log_sys.lsn - log_sys.last_checkpoint_lsn);
export_vars.innodb_checkpoint_max_age = static_cast<ulint>(
log_sys.max_checkpoint_age);
-
log_mutex_exit();
+
+ export_vars.innodb_checkpoint_age = static_cast<ulint>(
+ export_vars.innodb_lsn_current
+ - export_vars.innodb_lsn_last_checkpoint);
}
struct srv_monitor_state_t
@@ -1460,7 +1460,6 @@ void srv_error_monitor_task(void*)
/* number of successive fatal timeouts observed */
static ulint fatal_cnt;
static lsn_t old_lsn = recv_sys.recovered_lsn;
- lsn_t new_lsn;
/* longest waiting thread for a semaphore */
os_thread_id_t waiter;
static os_thread_id_t old_waiter = os_thread_get_curr_id();
@@ -1473,18 +1472,17 @@ void srv_error_monitor_task(void*)
/* Try to track a strange bug reported by Harald Fuchs and others,
where the lsn seems to decrease at times */
- if (log_peek_lsn(&new_lsn)) {
- if (new_lsn < old_lsn) {
+ lsn_t new_lsn = log_sys.get_lsn();
+ if (new_lsn < old_lsn) {
ib::error() << "Old log sequence number " << old_lsn << " was"
<< " greater than the new log sequence number "
<< new_lsn << ". Please submit a bug report to"
" https://jira.mariadb.org/";
ut_ad(0);
- }
-
- old_lsn = new_lsn;
}
+ old_lsn = new_lsn;
+
/* Update the statistics collected for deciding LRU
eviction policy. */
buf_LRU_stat_update();
@@ -1683,7 +1681,7 @@ srv_sync_log_buffer_in_background(void)
srv_main_thread_op_info = "flushing log";
if (difftime(current_time, srv_last_log_flush_time)
>= srv_flush_log_at_timeout) {
- log_buffer_sync_in_background(true);
+ log_sys.initiate_write(true);
srv_last_log_flush_time = current_time;
srv_log_writes_and_flush++;
}
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 40a825f558d..ca45e6e613d 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -323,23 +323,22 @@ static dberr_t create_log_file(lsn_t lsn, std::string& logfile0)
return DB_ERROR;
}
ut_d(recv_no_log_write = false);
- log_sys.lsn = ut_uint64_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE);
-
- log_sys.log.set_lsn(log_sys.lsn);
+ lsn = ut_uint64_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE);
+ log_sys.set_lsn(lsn + LOG_BLOCK_HDR_SIZE);
+ log_sys.log.set_lsn(lsn);
log_sys.log.set_lsn_offset(LOG_FILE_HDR_SIZE);
log_sys.buf_next_to_write = 0;
- log_sys.write_lsn = log_sys.lsn;
+ log_sys.write_lsn = lsn;
log_sys.next_checkpoint_no = 0;
log_sys.last_checkpoint_lsn = 0;
memset(log_sys.buf, 0, srv_log_buffer_size);
- log_block_init(log_sys.buf, log_sys.lsn);
+ log_block_init(log_sys.buf, lsn);
log_block_set_first_rec_group(log_sys.buf, LOG_BLOCK_HDR_SIZE);
log_sys.buf_free = LOG_BLOCK_HDR_SIZE;
- log_sys.lsn += LOG_BLOCK_HDR_SIZE;
log_mutex_exit();
@@ -991,9 +990,9 @@ static lsn_t srv_prepare_to_delete_redo_log_file(bool old_exists)
log_mutex_enter();
- fil_names_clear(log_sys.lsn, false);
+ fil_names_clear(log_sys.get_lsn(), false);
- flushed_lsn = log_sys.lsn;
+ flushed_lsn = log_sys.get_lsn();
{
ib::info info;
@@ -1028,10 +1027,9 @@ static lsn_t srv_prepare_to_delete_redo_log_file(bool old_exists)
<< " bytes; LSN=" << flushed_lsn;
}
- bool do_flush_logs = flushed_lsn != log_sys.flushed_to_disk_lsn;
log_mutex_exit();
- if (do_flush_logs) {
+ if (flushed_lsn != log_sys.get_flushed_lsn()) {
log_write_up_to(flushed_lsn, false);
}
log_sys.log.flush_data_only();