diff options
Diffstat (limited to 'storage/innobase/log/log0log.cc')
-rw-r--r-- | storage/innobase/log/log0log.cc | 116 |
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" |