diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-01-04 07:40:31 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-01-04 07:40:31 +0200 |
commit | 4c3ad24413f234599eda27f4958dd3ff21df3203 (patch) | |
tree | 11a4789464111628d22cdb189d1797e0e4ec2161 | |
parent | eab89f14ab0069a3f74e80bdf13aa70d85738c79 (diff) | |
download | mariadb-git-4c3ad24413f234599eda27f4958dd3ff21df3203.tar.gz |
MDEV-27416 InnoDB hang in buf_flush_wait_flushed(), on log checkpointbb-10.5-MDEV-27416
InnoDB could sometimes hang when triggering a log checkpoint. This is
due to commit 7b1252c03d7131754d9503560fe507b33ca1f8b4 (MDEV-24278),
which introduced an untimed wait to buf_flush_page_cleaner().
The hang was noticed by occasional failures of IMPORT TABLESPACE tests,
such as innodb.innodb-wl5522, which would (unnecessarily) invoke
log_make_checkpoint() from row_import_cleanup().
The reason of the hang was that buf_flush_page_cleaner() would enter
untimed sleep despite buf_flush_sync_lsn being set. The exact failure
scenario is unclear, because buf_flush_sync_lsn should actually be
protected by buf_pool.flush_list_mutex. We prevent the hang by
invoking buf_pool.page_cleaner_set_idle(false) whenever we are
setting buf_flush_sync_lsn and signaling buf_pool.do_flush_list.
The bulk of these changes was originally developed as a preparation
for MDEV-26827, to invoke buf_flush_list() from fewer threads,
and tested on 10.6 by Matthias Leich.
This fix was tested by running 100 repetitions of 100 concurrent instances
of the test innodb.innodb-wl5522 on a RelWithDebInfo build, using ext4fs
and innodb_flush_method=O_DIRECT on a SATA SSD with 4096-byte block size.
During the test, the call to log_make_checkpoint() in row_import_cleanup()
was present.
buf_flush_list(): Make static.
buf_flush_wait(): Wait for buf_pool.get_oldest_modification()
to reach a target, by work done in the buf_flush_page_cleaner.
If buf_flush_sync_lsn is going to be set, we will invoke
buf_pool.page_cleaner_set_idle(false).
buf_flush_ahead(): If buf_flush_sync_lsn or buf_flush_async_lsn
is going to be set and the page cleaner woken up, we will invoke
buf_pool.page_cleaner_set_idle(false).
buf_flush_wait_flushed(): Invoke buf_flush_wait().
buf_flush_sync(): Invoke recv_sys.apply() at the start in case
crash recovery is active. Invoke buf_flush_wait().
buf_flush_sync_batch(): A lower-level variant of buf_flush_sync()
that is only called by recv_sys_t::apply().
buf_flush_sync_for_checkpoint(): Do not trigger log apply
or checkpoint during recovery.
buf_dblwr_t::create(): Only initiate a buffer pool flush, not
a checkpoint.
row_import_cleanup(): Do not unnecessarily invoke log_make_checkpoint().
Invoking buf_flush_list_space() before starting to generate redo log
for the imported tablespace should suffice.
srv_prepare_to_delete_redo_log_file():
Set recv_sys.recovery_on in order to prevent
buf_flush_sync_for_checkpoint() from initiating a checkpoint
while the log is inaccessible. Remove a wait loop that is already
part of buf_flush_sync().
Do not invoke fil_names_clear() if the log is being upgraded,
because the FILE_MODIFY record is specific to the latest format.
create_log_file(): Clear recv_sys.recovery_on only after calling
log_make_checkpoint(), to prevent buf_flush_page_cleaner from
invoking a checkpoint.
innodb_shutdown(): Simplify the logic in mariadb-backup --prepare.
os_aio_wait_until_no_pending_writes(): Update the function comment.
Apart from row_quiesce_table_start() during FLUSH TABLES...FOR EXPORT,
this is being called by buf_flush_list_space(), which is invoked
by ALTER TABLE...IMPORT TABLESPACE as well as some encryption operations.
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 5 | ||||
-rw-r--r-- | storage/innobase/buf/buf0dblwr.cc | 3 | ||||
-rw-r--r-- | storage/innobase/buf/buf0flu.cc | 112 | ||||
-rw-r--r-- | storage/innobase/include/buf0flu.h | 11 | ||||
-rw-r--r-- | storage/innobase/include/os0file.h | 3 | ||||
-rw-r--r-- | storage/innobase/include/srv0srv.h | 2 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 2 | ||||
-rw-r--r-- | storage/innobase/os/os0file.cc | 3 | ||||
-rw-r--r-- | storage/innobase/row/row0import.cc | 2 | ||||
-rw-r--r-- | storage/innobase/srv/srv0srv.cc | 2 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 149 |
11 files changed, 155 insertions, 139 deletions
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 1c126191df3..37f99a94cee 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -3300,10 +3300,7 @@ re_evict: fix_block->fix(); mysql_mutex_unlock(&buf_pool.mutex); - buf_flush_list(); - buf_flush_wait_batch_end_acquiring_mutex(false); - while (buf_flush_list_space(space)); - os_aio_wait_until_no_pending_writes(); + buf_flush_sync(); if (fix_block->page.buf_fix_count() == 1 && !fix_block->page.oldest_modification()) { diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 52e947b7c5e..1d582b6cfbf 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -219,8 +219,7 @@ too_small: trx_sys_block->frame, TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N); mtr.commit(); - /* Flush the modified pages to disk and make a checkpoint */ - log_make_checkpoint(); + buf_flush_wait_flushed(mtr.commit_lsn()); /* Remove doublewrite pages from LRU */ buf_pool_invalidate(); diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 3c234228771..4b3e6e6e77e 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1538,7 +1538,7 @@ void buf_flush_wait_batch_end(bool lru) @param lsn buf_pool.get_oldest_modification(LSN_MAX) target @return the number of processed pages @retval 0 if a buf_pool.flush_list batch is already running */ -ulint buf_flush_list(ulint max_n, lsn_t lsn) +static ulint buf_flush_list(ulint max_n= ULINT_UNDEFINED, lsn_t lsn= LSN_MAX) { ut_ad(lsn); @@ -1833,6 +1833,30 @@ ATTRIBUTE_COLD void log_make_checkpoint() while (!log_checkpoint()); } +/** Wait for all dirty pages up to an LSN to be written out. +NOTE: The calling thread is not allowed to hold any buffer page latches! */ +static void buf_flush_wait(lsn_t lsn) +{ + ut_ad(lsn <= log_sys.get_lsn()); + + while (buf_pool.get_oldest_modification(lsn) < lsn) + { + if (buf_flush_sync_lsn < lsn) + { + buf_flush_sync_lsn= lsn; + buf_pool.page_cleaner_set_idle(false); + pthread_cond_signal(&buf_pool.do_flush_list); + } + my_cond_wait(&buf_pool.done_flush_list, + &buf_pool.flush_list_mutex.m_mutex); + } + + /* Wait for the checkpoint. */ + while (buf_flush_sync_lsn) + my_cond_wait(&buf_pool.done_flush_list, + &buf_pool.flush_list_mutex.m_mutex); +} + /** 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) @@ -1849,9 +1873,9 @@ ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn) if (buf_pool.get_oldest_modification(sync_lsn) < sync_lsn) { + MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS); #if 1 /* FIXME: remove this, and guarantee that the page cleaner serves us */ - if (UNIV_UNLIKELY(!buf_page_cleaner_is_active) - ut_d(|| innodb_page_cleaner_disabled_debug)) + if (UNIV_UNLIKELY(!buf_page_cleaner_is_active)) { do { @@ -1864,35 +1888,21 @@ ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn) MONITOR_FLUSH_SYNC_COUNT, MONITOR_FLUSH_SYNC_PAGES, n_pages); } - MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS); mysql_mutex_lock(&buf_pool.flush_list_mutex); } while (buf_pool.get_oldest_modification(sync_lsn) < sync_lsn); - - goto try_checkpoint; } + else #endif - if (buf_flush_sync_lsn < sync_lsn) - { - buf_flush_sync_lsn= sync_lsn; - pthread_cond_signal(&buf_pool.do_flush_list); - } - - do { - tpool::tpool_wait_begin(); thd_wait_begin(nullptr, THD_WAIT_DISKIO); - my_cond_wait(&buf_pool.done_flush_list, - &buf_pool.flush_list_mutex.m_mutex); - thd_wait_end(nullptr); + tpool::tpool_wait_begin(); + buf_flush_wait(sync_lsn); tpool::tpool_wait_end(); - - MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS); + thd_wait_end(nullptr); } - while (buf_pool.get_oldest_modification(sync_lsn) < sync_lsn); } -try_checkpoint: mysql_mutex_unlock(&buf_pool.flush_list_mutex); if (UNIV_UNLIKELY(log_sys.last_checkpoint_lsn < sync_lsn)) @@ -1925,8 +1935,11 @@ ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious) { mysql_mutex_lock(&buf_pool.flush_list_mutex); if (limit < lsn) + { limit= lsn; - pthread_cond_signal(&buf_pool.do_flush_list); + buf_pool.page_cleaner_set_idle(false); + pthread_cond_signal(&buf_pool.do_flush_list); + } mysql_mutex_unlock(&buf_pool.flush_list_mutex); } } @@ -1960,10 +1973,6 @@ ATTRIBUTE_COLD static void buf_flush_sync_for_checkpoint(lsn_t lsn) MONITOR_FLUSH_SYNC_PAGES, n_flushed); } - /* Attempt to perform a log checkpoint upon completing each batch. */ - if (recv_recovery_is_on()) - recv_sys.apply(true); - switch (srv_file_flush_method) { case SRV_NOSYNC: case SRV_O_DIRECT_NO_FSYNC: @@ -1980,7 +1989,8 @@ ATTRIBUTE_COLD static void buf_flush_sync_for_checkpoint(lsn_t lsn) mysql_mutex_unlock(&log_sys.flush_order_mutex); const lsn_t checkpoint_lsn= measure ? measure : newest_lsn; - if (checkpoint_lsn > log_sys.last_checkpoint_lsn + SIZE_OF_FILE_CHECKPOINT) + if (!recv_recovery_is_on() && + checkpoint_lsn > log_sys.last_checkpoint_lsn + SIZE_OF_FILE_CHECKPOINT) { mysql_mutex_unlock(&buf_pool.flush_list_mutex); log_checkpoint_low(checkpoint_lsn, newest_lsn); @@ -2004,7 +2014,7 @@ ATTRIBUTE_COLD static void buf_flush_sync_for_checkpoint(lsn_t lsn) else if (measure >= buf_flush_async_lsn) buf_flush_async_lsn= 0; - /* wake up buf_flush_wait_flushed() */ + /* wake up buf_flush_wait() */ pthread_cond_broadcast(&buf_pool.done_flush_list); lsn= std::max(lsn, target); @@ -2264,7 +2274,7 @@ furious_flush: if (UNIV_UNLIKELY(lsn_limit != 0)) { buf_flush_sync_lsn= 0; - /* wake up buf_flush_wait_flushed() */ + /* wake up buf_flush_wait() */ pthread_cond_broadcast(&buf_pool.done_flush_list); } unemployed: @@ -2334,7 +2344,7 @@ unemployed: if (UNIV_UNLIKELY(lsn_limit != 0)) { n_flushed= buf_flush_list(srv_max_io_capacity, lsn_limit); - /* wake up buf_flush_wait_flushed() */ + /* wake up buf_flush_wait() */ pthread_cond_broadcast(&buf_pool.done_flush_list); goto try_checkpoint; } @@ -2440,6 +2450,7 @@ ATTRIBUTE_COLD void buf_flush_page_cleaner_init() os_thread_create(buf_flush_page_cleaner); } +#if defined(HAVE_SYSTEMD) && !defined(EMBEDDED_LIBRARY) /** @return the number of dirty pages in the buffer pool */ static ulint buf_flush_list_length() { @@ -2448,6 +2459,7 @@ static ulint buf_flush_list_length() mysql_mutex_unlock(&buf_pool.flush_list_mutex); return len; } +#endif /** Flush the buffer pool on shutdown. */ ATTRIBUTE_COLD void buf_flush_buffer_pool() @@ -2458,13 +2470,15 @@ ATTRIBUTE_COLD void buf_flush_buffer_pool() service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, "Waiting to flush the buffer pool"); - while (buf_pool.n_flush_list() || buf_flush_list_length()) + mysql_mutex_lock(&buf_pool.flush_list_mutex); + + while (buf_pool.get_oldest_modification(0)) { + mysql_mutex_unlock(&buf_pool.flush_list_mutex); buf_flush_list(srv_max_io_capacity); - timespec abstime; - if (buf_pool.n_flush_list()) { + timespec abstime; service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, "Waiting to flush " ULINTPF " pages", buf_flush_list_length()); @@ -2475,24 +2489,48 @@ ATTRIBUTE_COLD void buf_flush_buffer_pool() &abstime); mysql_mutex_unlock(&buf_pool.mutex); } + mysql_mutex_lock(&buf_pool.flush_list_mutex); } + mysql_mutex_unlock(&buf_pool.flush_list_mutex); ut_ad(!buf_pool.any_io_pending()); } +/** Synchronously flush dirty blocks during recv_sys_t::apply(). +NOTE: The calling thread is not allowed to hold any buffer page latches! */ +void buf_flush_sync_batch(lsn_t lsn) +{ + thd_wait_begin(nullptr, THD_WAIT_DISKIO); + tpool::tpool_wait_begin(); + mysql_mutex_lock(&buf_pool.flush_list_mutex); + buf_flush_wait(lsn); + mysql_mutex_unlock(&buf_pool.flush_list_mutex); + tpool::tpool_wait_end(); + thd_wait_end(nullptr); +} + /** Synchronously flush dirty blocks. NOTE: The calling thread is not allowed to hold any buffer page latches! */ void buf_flush_sync() { ut_ad(!sync_check_iterate(dict_sync_check())); + if (recv_recovery_is_on()) + recv_sys.apply(true); + + thd_wait_begin(nullptr, THD_WAIT_DISKIO); + tpool::tpool_wait_begin(); + mysql_mutex_lock(&buf_pool.flush_list_mutex); for (;;) { - const ulint n_flushed= buf_flush_list(srv_max_io_capacity); - buf_flush_wait_batch_end_acquiring_mutex(false); - if (!n_flushed && !buf_flush_list_length()) - return; + const lsn_t lsn= log_sys.get_lsn(); + buf_flush_wait(lsn); + if (lsn == log_sys.get_lsn()) + break; } + mysql_mutex_unlock(&buf_pool.flush_list_mutex); + tpool::tpool_wait_end(); + thd_wait_end(nullptr); } #ifdef UNIV_DEBUG diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index 8d45cf2be38..e1be95ebcd0 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -85,13 +85,6 @@ buf_flush_init_for_writing( void* page_zip_, bool use_full_checksum); -/** 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 -@return the number of processed pages -@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 @@ -144,6 +137,10 @@ ATTRIBUTE_COLD void buf_flush_buffer_pool(); void buf_flush_validate(); #endif /* UNIV_DEBUG */ +/** Synchronously flush dirty blocks during recv_sys_t::apply(). +NOTE: The calling thread is not allowed to hold any buffer page latches! */ +void buf_flush_sync_batch(lsn_t lsn); + /** Synchronously flush dirty blocks. NOTE: The calling thread is not allowed to hold any buffer page latches! */ void buf_flush_sync(); diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 8f632305f7e..ba252433315 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -1111,8 +1111,7 @@ 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); -/** Wait until there are no pending asynchronous writes. -Only used on FLUSH TABLES...FOR EXPORT. */ +/** Wait until there are no pending asynchronous writes. */ void os_aio_wait_until_no_pending_writes(); diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index a5bebc34c39..fe2c33e219f 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -511,7 +511,7 @@ do { \ #ifdef HAVE_PSI_STAGE_INTERFACE /** Performance schema stage event for monitoring ALTER TABLE progress -everything after flush log_make_checkpoint(). */ +in ha_innobase::commit_inplace_alter_table(). */ extern PSI_stage_info srv_stage_alter_table_end; /** Performance schema stage event for monitoring ALTER TABLE progress diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 68bbf06ca49..9474cd31793 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2752,7 +2752,7 @@ next_page: /* Instead of flushing, last_batch could sort the buf_pool.flush_list in ascending order of buf_page_t::oldest_modification. */ - buf_flush_sync(); + buf_flush_sync_batch(recovered_lsn); if (!last_batch) { diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 9e1eeff202d..32c31b191ed 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -3821,8 +3821,7 @@ static void os_aio_wait_until_no_pending_writes_low() tpool::tpool_wait_end(); } -/** Wait until there are no pending asynchronous writes. -Only used on FLUSH TABLES...FOR EXPORT. */ +/** Wait until there are no pending asynchronous writes. */ void os_aio_wait_until_no_pending_writes() { os_aio_wait_until_no_pending_writes_low(); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 45cc8c278b5..3df29ac1830 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -2211,8 +2211,6 @@ row_import_cleanup( DBUG_EXECUTE_IF("ib_import_before_checkpoint_crash", DBUG_SUICIDE();); - log_make_checkpoint(); - return(err); } diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 73e67c12d58..c05562daca3 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -557,7 +557,7 @@ char srv_buffer_pool_load_at_startup = TRUE; #ifdef HAVE_PSI_STAGE_INTERFACE /** Performance schema stage event for monitoring ALTER TABLE progress -everything after flush log_make_checkpoint(). */ +in ha_innobase::commit_inplace_alter_table(). */ PSI_stage_info srv_stage_alter_table_end = {0, "alter table (end)", PSI_FLAG_STAGE_PROGRESS}; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index cf936893e1b..afb7834c9b9 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -329,6 +329,13 @@ static dberr_t create_log_file(bool create_new_db, lsn_t lsn, log_sys.log.write_header_durable(lsn); + ut_ad(srv_startup_is_before_trx_rollback_phase); + if (create_new_db) { + srv_startup_is_before_trx_rollback_phase = false; + } + + /* Enable checkpoints in buf_flush_page_cleaner(). */ + recv_sys.recovery_on = false; mysql_mutex_unlock(&log_sys.mutex); log_make_checkpoint(); @@ -895,91 +902,74 @@ buffer pools. Flush the redo log buffer to the redo log file. @return lsn upto which data pages have been flushed. */ static lsn_t srv_prepare_to_delete_redo_log_file(bool old_exists) { - DBUG_ENTER("srv_prepare_to_delete_redo_log_file"); + DBUG_ENTER("srv_prepare_to_delete_redo_log_file"); - lsn_t flushed_lsn; - ulint count = 0; + /* Disable checkpoints in the page cleaner. */ + ut_ad(!recv_sys.recovery_on); + recv_sys.recovery_on= true; - if (log_sys.log.subformat != 2) { - srv_log_file_size = 0; - } + /* Clean the buffer pool. */ + buf_flush_sync(); - for (;;) { - /* Clean the buffer pool. */ - buf_flush_sync(); + if (log_sys.log.subformat != 2) + srv_log_file_size= 0; - DBUG_EXECUTE_IF("innodb_log_abort_1", DBUG_RETURN(0);); - DBUG_PRINT("ib_log", ("After innodb_log_abort_1")); + DBUG_EXECUTE_IF("innodb_log_abort_1", DBUG_RETURN(0);); + DBUG_PRINT("ib_log", ("After innodb_log_abort_1")); - mysql_mutex_lock(&log_sys.mutex); - - fil_names_clear(log_sys.get_lsn(), false); - - flushed_lsn = log_sys.get_lsn(); - - { - ib::info info; - if (srv_log_file_size == 0 - || (log_sys.log.format & ~log_t::FORMAT_ENCRYPTED) - != log_t::FORMAT_10_5) { - info << "Upgrading redo log: "; - } else if (!old_exists - || srv_log_file_size - != srv_log_file_size_requested) { - if (srv_encrypt_log - == (my_bool)log_sys.is_encrypted()) { - info << (srv_encrypt_log - ? "Resizing encrypted" - : "Resizing"); - } else if (srv_encrypt_log) { - info << "Encrypting and resizing"; - } else { - info << "Removing encryption" - " and resizing"; - } - - info << " redo log from " << srv_log_file_size - << " to "; - } else if (srv_encrypt_log) { - info << "Encrypting redo log: "; - } else { - info << "Removing redo log encryption: "; - } - - info << srv_log_file_size_requested - << " bytes; LSN=" << flushed_lsn; - } + mysql_mutex_lock(&log_sys.mutex); + const bool latest_format= (log_sys.log.format & ~log_t::FORMAT_ENCRYPTED) == + log_t::FORMAT_10_5; + lsn_t flushed_lsn= log_sys.get_lsn(); - mysql_mutex_unlock(&log_sys.mutex); + if (latest_format) + { + fil_names_clear(flushed_lsn, false); + flushed_lsn= log_sys.get_lsn(); + } - if (flushed_lsn != log_sys.get_flushed_lsn()) { - log_write_up_to(flushed_lsn, false); - log_sys.log.flush(); - } + { + const char *msg; + if (!latest_format || srv_log_file_size == 0) + { + msg= "Upgrading redo log: "; +same_size: + ib::info() << msg << srv_log_file_size_requested << " bytes; LSN=" + << flushed_lsn; + } + else if (old_exists && srv_log_file_size == srv_log_file_size_requested) + { + msg= srv_encrypt_log + ? "Encrypting redo log: " : "Removing redo log encryption: "; + goto same_size; + } + else + { + if (srv_encrypt_log == (my_bool)log_sys.is_encrypted()) + msg= srv_encrypt_log ? "Resizing encrypted" : "Resizing"; + else + msg= srv_encrypt_log + ? "Encrypting and resizing" + : "Removing encryption and resizing"; + + ib::info() << msg << " redo log from " << srv_log_file_size << " to " + << srv_log_file_size_requested + << " bytes; LSN=" << flushed_lsn; + } + } - ut_ad(flushed_lsn == log_sys.get_lsn()); - - /* Check if the buffer pools are clean. If not - retry till it is clean. */ - if (ulint pending_io = buf_pool.io_pending()) { - count++; - /* Print a message every 60 seconds if we - are waiting to clean the buffer pools */ - if (srv_print_verbose_log && count > 600) { - ib::info() << "Waiting for " - << pending_io << " buffer " - << "page I/Os to complete"; - count = 0; - } + mysql_mutex_unlock(&log_sys.mutex); - os_thread_sleep(100000); - continue; - } + if (flushed_lsn != log_sys.get_flushed_lsn()) + { + log_write_up_to(flushed_lsn, false); + log_sys.log.flush(); + } - break; - } + ut_ad(flushed_lsn == log_sys.get_lsn()); + ut_ad(!buf_pool.any_io_pending()); - DBUG_RETURN(flushed_lsn); + DBUG_RETURN(flushed_lsn); } /** Tries to locate LOG_FILE_NAME and check it's size, etc @@ -1259,7 +1249,7 @@ dberr_t srv_start(bool create_new_db) ut_ad(buf_page_cleaner_is_active); } - srv_startup_is_before_trx_rollback_phase = !create_new_db; + srv_startup_is_before_trx_rollback_phase = true; /* Check if undo tablespaces and redo log files exist before creating a new system tablespace */ @@ -1308,7 +1298,6 @@ dberr_t srv_start(bool create_new_db) if (create_new_db) { flushed_lsn = log_sys.get_lsn(); log_sys.set_flushed_lsn(flushed_lsn); - buf_flush_sync(); err = create_log_file(true, flushed_lsn, logfile0); @@ -1371,6 +1360,9 @@ dberr_t srv_start(bool create_new_db) if (!log_set_capacity(srv_log_file_size_requested)) { return(srv_init_abort(DB_ERROR)); } + + /* Enable checkpoints in the page cleaner. */ + recv_sys.recovery_on = false; } file_checked: @@ -2024,11 +2016,8 @@ void innodb_shutdown() break; case SRV_OPERATION_RESTORE: case SRV_OPERATION_RESTORE_EXPORT: - srv_shutdown_state = SRV_SHUTDOWN_CLEANUP; - if (!buf_page_cleaner_is_active) { - break; - } mysql_mutex_lock(&buf_pool.flush_list_mutex); + srv_shutdown_state = SRV_SHUTDOWN_CLEANUP; while (buf_page_cleaner_is_active) { pthread_cond_signal(&buf_pool.do_flush_list); my_cond_wait(&buf_pool.done_flush_list, |