diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index ab4938136b0..5ef6af65f6f 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1912,7 +1912,8 @@ inline void log_t::write_checkpoint(lsn_t end_lsn) noexcept resize_flush_buf= nullptr; resize_target= 0; resize_lsn.store(0, std::memory_order_relaxed); - writer_update(); + resize_initiator= nullptr; + writer_update(false); } log_resize_release(); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 19a27510762..7e9439a760c 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -18605,7 +18605,7 @@ static void innodb_log_file_size_update(THD *thd, st_mysql_sys_var*, " innodb_log_buffer_size=%u", MYF(0), log_sys.buf_size); else { - switch (log_sys.resize_start(*static_cast(save))) { + switch (log_sys.resize_start(*static_cast(save), thd)) { case log_t::RESIZE_NO_CHANGE: break; case log_t::RESIZE_IN_PROGRESS: @@ -18617,12 +18617,11 @@ static void innodb_log_file_size_update(THD *thd, st_mysql_sys_var*, ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_CANT_CREATE_HANDLER_FILE); break; case log_t::RESIZE_STARTED: - const lsn_t start{log_sys.resize_in_progress()}; for (timespec abstime;;) { if (thd_kill_level(thd)) { - log_sys.resize_abort(); + log_sys.resize_abort(thd); break; } @@ -18637,13 +18636,15 @@ static void innodb_log_file_size_update(THD *thd, st_mysql_sys_var*, resizing= log_sys.resize_in_progress(); } mysql_mutex_unlock(&buf_pool.flush_list_mutex); - if (start > log_sys.get_lsn()) + if (!resizing || !log_sys.resize_running(thd)) + break; + if (resizing > log_sys.get_lsn()) { ut_ad(!log_sys.is_mmap()); /* The server is almost idle. Write dummy FILE_CHECKPOINT records to ensure that the log resizing will complete. */ log_sys.latch.wr_lock(SRW_LOCK_CALL); - while (start > log_sys.get_lsn()) + while (resizing > log_sys.get_lsn()) { mtr_t mtr; mtr.start(); @@ -18651,8 +18652,6 @@ static void innodb_log_file_size_update(THD *thd, st_mysql_sys_var*, } log_sys.latch.wr_unlock(); } - if (!resizing || resizing > start /* only wait for our resize */) - break; } } } diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 2ca34a93789..33df9d39ba6 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -303,7 +303,6 @@ public: bool log_maybe_unbuffered; # endif #endif - /** Fields involved in checkpoints @{ */ lsn_t log_capacity; /*!< capacity of the log; if the checkpoint age exceeds this, it is @@ -326,6 +325,8 @@ public: /* @} */ private: + /** the thread that initiated resize_lsn() */ + Atomic_relaxed resize_initiator; /** A lock when the spin-only lock_lsn() is not being used */ log_lsn_lock lsn_lock; public: @@ -367,11 +368,17 @@ public: /** Start resizing the log and release the exclusive latch. @param size requested new file_size + @param thd the current thread identifier @return whether the resizing was started successfully */ - resize_start_status resize_start(os_offset_t size) noexcept; + resize_start_status resize_start(os_offset_t size, void *thd) noexcept; - /** Abort any resize_start(). */ - void resize_abort() noexcept; + /** Abort a resize_start() that we started. + @param thd thread identifier that had been passed to resize_start() */ + void resize_abort(void *thd) noexcept; + + /** @return whether a particular resize_start() is in progress */ + bool resize_running(void *thd) const noexcept + { return thd == resize_initiator; } /** Replicate a write to the log. @param lsn start LSN @@ -481,7 +488,7 @@ public: private: /** Update writer and mtr_t::finisher */ - void writer_update() noexcept; + void writer_update(bool resizing) noexcept; /** Wait in append_prepare() for buffer to become available @tparam spin whether to use the spin-only lock_lsn() diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 0e9d4c9ad45..d35f66a78ec 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -353,7 +353,7 @@ bool log_t::attach(log_file_t file, os_offset_t size) # endif buf= static_cast(ptr); max_buf_free= 1; - writer_update(); + writer_update(false); # ifdef HAVE_PMEM if (is_pmem) return true; @@ -395,7 +395,7 @@ bool log_t::attach(log_file_t file, os_offset_t size) TRASH_ALLOC(buf, buf_size); TRASH_ALLOC(flush_buf, buf_size); max_buf_free= buf_size / LOG_BUF_FLUSH_RATIO - LOG_BUF_FLUSH_MARGIN; - writer_update(); + writer_update(false); memset_aligned<512>(checkpoint_buf, 0, write_size); func_exit: @@ -570,31 +570,35 @@ void log_t::set_buffered(bool buffered) /** Start resizing the log and release the exclusive latch. @param size requested new file_size +@param thd the current thread identifier @return whether the resizing was started successfully */ -log_t::resize_start_status log_t::resize_start(os_offset_t size) noexcept +log_t::resize_start_status log_t::resize_start(os_offset_t size, void *thd) + noexcept { ut_ad(size >= 4U << 20); ut_ad(!(size & 4095)); ut_ad(!srv_read_only_mode); + ut_ad(thd); log_resize_acquire(); - resize_start_status status= RESIZE_NO_CHANGE; - lsn_t start_lsn{0}; -#ifdef HAVE_PMEM - bool is_pmem{false}; -#endif + resize_start_status status; - if (resize_in_progress()) + if (size == file_size) + status= RESIZE_NO_CHANGE; + else if (resize_in_progress()) status= RESIZE_IN_PROGRESS; - else if (size != file_size) + else { + lsn_t start_lsn; ut_ad(!resize_in_progress()); ut_ad(!resize_log.is_opened()); ut_ad(!resize_buf); ut_ad(!resize_flush_buf); + ut_ad(!resize_initiator); std::string path{get_log_file_path("ib_logfile101")}; bool success; + resize_initiator= thd; resize_lsn.store(1, std::memory_order_relaxed); resize_target= 0; resize_log.m_file= @@ -612,6 +616,7 @@ log_t::resize_start_status log_t::resize_start(os_offset_t size) noexcept #ifdef HAVE_PMEM else if (is_mmap()) { + bool is_pmem{false}; ptr= ::log_mmap(resize_log.m_file, is_pmem, size); if (ptr == MAP_FAILED) @@ -661,34 +666,33 @@ log_t::resize_start_status log_t::resize_start(os_offset_t size) noexcept else if (!is_opened()) resize_log.close(); - writer_update(); + resize_lsn.store(start_lsn, std::memory_order_relaxed); + writer_update(true); + log_resize_release(); + + mysql_mutex_lock(&buf_pool.flush_list_mutex); + lsn_t target_lsn= buf_pool.get_oldest_modification(0); + mysql_mutex_unlock(&buf_pool.flush_list_mutex); + buf_flush_ahead(start_lsn < target_lsn ? target_lsn + 1 : start_lsn, + false); + return RESIZE_STARTED; } - status= success ? RESIZE_STARTED : RESIZE_FAILED; } - resize_lsn.store(start_lsn, std::memory_order_relaxed); + resize_initiator= nullptr; + resize_lsn.store(0, std::memory_order_relaxed); + status= RESIZE_FAILED; } log_resize_release(); - - if (start_lsn) - { - mysql_mutex_lock(&buf_pool.flush_list_mutex); - lsn_t target_lsn= buf_pool.get_oldest_modification(0); - if (start_lsn < target_lsn) - start_lsn= target_lsn + 1; - mysql_mutex_unlock(&buf_pool.flush_list_mutex); - buf_flush_ahead(start_lsn, false); - } - return status; } -/** Abort log resizing. */ -void log_t::resize_abort() noexcept +/** Abort a resize_start() that we started. */ +void log_t::resize_abort(void *thd) noexcept { log_resize_acquire(); - if (resize_in_progress() > 1) + if (resize_running(thd)) { #ifdef HAVE_PMEM const bool is_mmap{this->is_mmap()}; @@ -715,11 +719,12 @@ void log_t::resize_abort() noexcept resize_buf= nullptr; resize_target= 0; resize_lsn.store(0, std::memory_order_relaxed); + resize_initiator= nullptr; std::string path{get_log_file_path("ib_logfile101")}; IF_WIN(DeleteFile(path.c_str()), unlink(path.c_str())); + writer_update(false); } - writer_update(); log_resize_release(); } @@ -1190,10 +1195,11 @@ ATTRIBUTE_COLD static lsn_t log_writer_resizing() noexcept return log_sys.write_buf(); } -void log_t::writer_update() noexcept +void log_t::writer_update(bool resizing) noexcept { ut_ad(latch_have_wr()); - writer= resize_in_progress() ? log_writer_resizing : log_writer; + ut_ad(resizing == (resize_in_progress() > 1)); + writer= resizing ? log_writer_resizing : log_writer; mtr_t::finisher_update(); }