summaryrefslogtreecommitdiff
path: root/storage/innobase/log/log0log.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/log/log0log.cc')
-rw-r--r--storage/innobase/log/log0log.cc116
1 files changed, 62 insertions, 54 deletions
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 090acc86843..7563f30e8fb 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -493,7 +493,7 @@ void log_t::create()
log record has a non-zero start lsn, a fact which we will use */
set_lsn(LOG_START_LSN + LOG_BLOCK_HDR_SIZE);
- set_flushed_lsn(0);
+ set_flushed_lsn(LOG_START_LSN + LOG_BLOCK_HDR_SIZE);
ut_ad(srv_log_buffer_size >= 16 * OS_FILE_LOG_BLOCK_SIZE);
ut_ad(srv_log_buffer_size >= 4U << srv_page_size_shift);
@@ -936,7 +936,8 @@ loop:
and invoke log_mutex_enter(). */
static void log_write_flush_to_disk_low(lsn_t lsn)
{
- log_sys.log.flush();
+ if (!log_sys.log.writes_are_durable())
+ log_sys.log.flush();
ut_a(lsn >= log_sys.get_flushed_lsn());
log_sys.set_flushed_lsn(lsn);
}
@@ -1129,12 +1130,7 @@ void log_write_up_to(lsn_t lsn, bool flush_to_disk, bool rotate_key)
/* Flush the highest written lsn.*/
auto flush_lsn = write_lock.value();
flush_lock.set_pending(flush_lsn);
-
- if (!log_sys.log.writes_are_durable())
- {
- log_write_flush_to_disk_low(flush_lsn);
- }
-
+ log_write_flush_to_disk_low(flush_lsn);
flush_lock.release(flush_lsn);
innobase_mysql_log_notify(flush_lsn);
@@ -1186,7 +1182,7 @@ this lsn
which means that we could not start this flush batch */
static bool log_preflush_pool_modified_pages(lsn_t new_oldest)
{
- bool success;
+ bool success;
if (recv_recovery_is_on()) {
/* If the recovery is running, we must first apply all
@@ -1204,29 +1200,22 @@ static bool log_preflush_pool_modified_pages(lsn_t new_oldest)
|| !buf_page_cleaner_is_active
|| srv_is_being_started) {
- ulint n_pages;
+ ulint n_pages = buf_flush_lists(ULINT_UNDEFINED, new_oldest);
- success = buf_flush_lists(ULINT_MAX, new_oldest, &n_pages);
+ buf_flush_wait_batch_end_acquiring_mutex(false);
- buf_flush_wait_batch_end(false);
-
- if (!success) {
- MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS);
- }
+ MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS);
MONITOR_INC_VALUE_CUMULATIVE(
MONITOR_FLUSH_SYNC_TOTAL_PAGE,
MONITOR_FLUSH_SYNC_COUNT,
MONITOR_FLUSH_SYNC_PAGES,
n_pages);
+
+ const lsn_t oldest = buf_pool.get_oldest_modification();
+ success = !oldest || oldest >= new_oldest;
} else {
/* better to wait for flushed by page cleaner */
-
- if (srv_flush_sync) {
- /* wake page cleaner for IO burst */
- buf_flush_request_force(new_oldest);
- }
-
buf_flush_wait_flushed(new_oldest);
success = true;
@@ -1515,6 +1504,41 @@ void log_check_margins()
extern void buf_resize_shutdown();
+/** @return the number of dirty pages in the buffer pool */
+static ulint flush_list_length()
+{
+ mysql_mutex_lock(&buf_pool.flush_list_mutex);
+ const ulint len= UT_LIST_GET_LEN(buf_pool.flush_list);
+ mysql_mutex_unlock(&buf_pool.flush_list_mutex);
+ return len;
+}
+
+static void flush_buffer_pool()
+{
+ service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL,
+ "Waiting to flush the buffer pool");
+ while (buf_pool.n_flush_list || flush_list_length())
+ {
+ buf_flush_lists(ULINT_UNDEFINED, LSN_MAX);
+ timespec abstime;
+
+ if (buf_pool.n_flush_list)
+ {
+ service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL,
+ "Waiting to flush " ULINTPF " pages",
+ flush_list_length());
+ set_timespec(abstime, INNODB_EXTEND_TIMEOUT_INTERVAL / 2);
+ mysql_mutex_lock(&buf_pool.mutex);
+ while (buf_pool.n_flush_list)
+ mysql_cond_timedwait(&buf_pool.done_flush_list, &buf_pool.mutex,
+ &abstime);
+ mysql_mutex_unlock(&buf_pool.mutex);
+ }
+ }
+
+ ut_ad(!buf_pool.any_io_pending());
+}
+
/** Make a checkpoint at the latest lsn on shutdown. */
void logs_empty_and_mark_files_at_shutdown()
{
@@ -1616,30 +1640,26 @@ wait_suspend_loop:
goto wait_suspend_loop;
}
- buf_load_dump_end();
-
- srv_shutdown_state = SRV_SHUTDOWN_FLUSH_PHASE;
+ if (buf_page_cleaner_is_active) {
+ thread_name = "page cleaner thread";
+ mysql_cond_signal(&buf_pool.do_flush_list);
+ goto wait_suspend_loop;
+ }
- /* At this point only page_cleaner should be active. We wait
- here to let it complete the flushing of the buffer pools
- before proceeding further. */
+ buf_load_dump_end();
- count = 0;
- service_manager_extend_timeout(COUNT_INTERVAL * CHECK_INTERVAL/1000000 * 2,
- "Waiting for page cleaner");
- while (buf_page_cleaner_is_active) {
- ++count;
- os_thread_sleep(CHECK_INTERVAL);
- if (srv_print_verbose_log && count > COUNT_INTERVAL) {
- service_manager_extend_timeout(COUNT_INTERVAL * CHECK_INTERVAL/1000000 * 2,
- "Waiting for page cleaner");
- ib::info() << "Waiting for page_cleaner to "
- "finish flushing of buffer pool";
- /* This is a workaround to avoid the InnoDB hang
- when OS datetime changed backwards */
- os_event_set(buf_flush_event);
+ if (!buf_pool.is_initialised()) {
+ ut_ad(!srv_was_started);
+ } else if (ulint pending_io = buf_pool.io_pending()) {
+ if (srv_print_verbose_log && count > 600) {
+ ib::info() << "Waiting for " << pending_io << " buffer"
+ " page I/Os to complete";
count = 0;
}
+
+ goto loop;
+ } else {
+ flush_buffer_pool();
}
if (log_sys.is_initialised()) {
@@ -1660,18 +1680,6 @@ wait_suspend_loop:
}
}
- if (!buf_pool.is_initialised()) {
- ut_ad(!srv_was_started);
- } else if (ulint pending_io = buf_pool.io_pending()) {
- if (srv_print_verbose_log && count > 600) {
- ib::info() << "Waiting for " << pending_io << " buffer"
- " page I/Os to complete";
- count = 0;
- }
-
- goto loop;
- }
-
if (srv_fast_shutdown == 2 || !srv_was_started) {
if (!srv_read_only_mode && srv_was_started) {
ib::info() << "MySQL has requested a very fast"