mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-38833 Suboptimal or dead code at server startup
The InnoDB bootstrap is creating unnecessary log checkpoints and even invalidating the buffer pool for no reason, making it necessary to read pages into the buffer pool during bootstrap. Furthermore, the page cleaner thread attempts to invoke recv_sys.apply(true), even though most calls were unreachable starting with commit685d958e38(MDEV-14425) if not earlier. buf_flush_sync(): Replaced with buf_flush_sync_batch(LSN_MAX), possibly preceded by recv_sys.apply(true). buf_pool_t::assert_all_freed(): Assert that buf_pool.mutex is being held by the caller. buf_dblwr_t::create(): Evict each doublewrite buffer pool page immediately from the buffer pool, so that there will be no need to invoke buf_pool_invalidate(). Also, remove the unnecessary call to buf_flush_wait_flushed(); there is nothing special about the doublewrite buffer creation ever since commite2c63a7062(MDEV-38595) made the redo logging actually crash-safe. buf_pool_invalidate(): Moved to the same compilation unit with the only remaining caller, recv_sys_t::apply(). srv_start(): Do not invoke buf_flush_sync(). We already created an initial checkpoint in log_t::create(lsn_t), and we will create the final one during shutdown. Together with the simplification of buf_dblwr_t::create(), this should noticeably speed up the server bootstrap. Also, simplify the log file rebuild by extending the critical section of log_sys.latch and buf_pool.flush_list_mutex. create_log_file(): Assert and assume that both log_sys.latch and buf_pool.flush_list_mutex were acquired by the caller. This prevents any race condition with buf_flush_page_cleaner() when the log is being rebuilt. srv_prepare_to_delete_redo_log_file(): Invoke recv_sys.apply(true) before invoking buf_flush_sync_batch(LSN_MAX). Remove a redundant call to fil_system.sys_space->open(false) because srv_start() must already have successfully invoked that in order for us to reach this code path. Remove some duplicated assertions as well as a redundant call to log_write_up_to() from the end. If we crash while rebuilding a latest_format log file, the subsequent startup will perform crash recovery normally. This avoids a redundant write to the old log.
This commit is contained in:
@@ -2698,9 +2698,14 @@ static bool innodb_init()
|
||||
}
|
||||
|
||||
ut_ad(srv_force_recovery <= SRV_FORCE_IGNORE_CORRUPT);
|
||||
mysql_mutex_lock(&recv_sys.mutex);
|
||||
ut_ad(recv_no_log_write);
|
||||
buf_flush_sync();
|
||||
if (recv_sys.recovery_on)
|
||||
recv_sys.apply(true);
|
||||
mysql_mutex_unlock(&recv_sys.mutex);
|
||||
recv_sys.debug_free();
|
||||
|
||||
buf_flush_sync_batch(LSN_MAX);
|
||||
ut_ad(!os_aio_pending_reads());
|
||||
ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex));
|
||||
ut_ad(!buf_pool.get_oldest_modification(0));
|
||||
|
||||
40
mysql-test/suite/innodb/r/log_file_size,release.rdiff
Normal file
40
mysql-test/suite/innodb/r/log_file_size,release.rdiff
Normal file
@@ -0,0 +1,40 @@
|
||||
--- log_file_size.result
|
||||
+++ log_file_size,release.result
|
||||
@@ -19,8 +19,6 @@
|
||||
42
|
||||
INSERT INTO t1 VALUES (0),(123);
|
||||
BEGIN;
|
||||
-SET GLOBAL innodb_limit_optimistic_insert_debug=2;
|
||||
-INSERT INTO t1 VALUES (124),(125),(126),(127),(128),(129);
|
||||
DELETE FROM t1 WHERE a>0;
|
||||
# Persist the state of the above incomplete transaction by
|
||||
# causing a redo log write for another transaction.
|
||||
@@ -34,22 +32,10 @@
|
||||
SELECT * FROM t1;
|
||||
ERROR 42000: Unknown storage engine 'InnoDB'
|
||||
FOUND 1 /syntax error in innodb_log_group_home_dir/ in mysqld.1.err
|
||||
-# restart: --debug=d,innodb_log_abort_1
|
||||
-SELECT * FROM t1;
|
||||
-ERROR 42000: Unknown storage engine 'InnoDB'
|
||||
-FOUND 1 /InnoDB: Starting crash recovery from checkpoint LSN=.*/ in mysqld.1.err
|
||||
# restart: --innodb-read-only
|
||||
SELECT * FROM t1;
|
||||
ERROR 42000: Unknown storage engine 'InnoDB'
|
||||
FOUND 1 /InnoDB: innodb_read_only prevents crash recovery/ in mysqld.1.err
|
||||
-# restart: --debug=d,innodb_log_abort_5
|
||||
-SELECT * FROM t1;
|
||||
-ERROR 42000: Unknown storage engine 'InnoDB'
|
||||
-FOUND 1 /redo log from 5\.000MiB to [0-9.]*[KMGT]iB/ in mysqld.1.err
|
||||
-# restart: --innodb-read-only
|
||||
-SELECT * FROM t1;
|
||||
-ERROR 42000: Unknown storage engine 'InnoDB'
|
||||
-FOUND 2 /InnoDB: innodb_read_only prevents crash recovery/ in mysqld.1.err
|
||||
# restart
|
||||
SELECT * FROM t1;
|
||||
ERROR 42000: Unknown storage engine 'InnoDB'
|
||||
@@ -66,4 +52,4 @@
|
||||
42
|
||||
123
|
||||
DROP TABLE t1;
|
||||
-FOUND 2 /InnoDB: Resizing redo log from 5\.000MiB to [0-9.]*[KMGT]iB; LSN=\d+\b/ in mysqld.1.err
|
||||
+FOUND 1 /InnoDB: Resizing redo log from 5\.000MiB to [0-9.]*[KMGT]iB; LSN=\d+\b/ in mysqld.1.err
|
||||
@@ -1,3 +1,4 @@
|
||||
SET GLOBAL innodb_file_per_table=0;
|
||||
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
# restart: --innodb-log-file-size=4m
|
||||
CHECK TABLE t1;
|
||||
@@ -18,6 +19,8 @@ a
|
||||
42
|
||||
INSERT INTO t1 VALUES (0),(123);
|
||||
BEGIN;
|
||||
SET GLOBAL innodb_limit_optimistic_insert_debug=2;
|
||||
INSERT INTO t1 VALUES (124),(125),(126),(127),(128),(129);
|
||||
DELETE FROM t1 WHERE a>0;
|
||||
# Persist the state of the above incomplete transaction by
|
||||
# causing a redo log write for another transaction.
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
--source include/innodb_page_size_small.inc
|
||||
# Embedded server tests do not support restarting
|
||||
--source include/not_embedded.inc
|
||||
# DBUG_EXECUTE_IF is needed
|
||||
--source include/have_debug.inc
|
||||
--source include/maybe_debug.inc
|
||||
# This test is slow on buildbot.
|
||||
--source include/big_test.inc
|
||||
|
||||
@@ -19,6 +18,7 @@ call mtr.add_suppression("InnoDB: Expecting only ib_logfile0");
|
||||
FLUSH TABLES;
|
||||
--enable_query_log
|
||||
let MYSQLD_DATADIR= `select @@datadir`;
|
||||
SET GLOBAL innodb_file_per_table=0;
|
||||
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
|
||||
--source include/shutdown_mysqld.inc
|
||||
@@ -88,6 +88,10 @@ INSERT INTO t1 VALUES (0),(123);
|
||||
let SEARCH_ABORT = NOT FOUND;
|
||||
|
||||
BEGIN;
|
||||
if ($have_debug) {
|
||||
SET GLOBAL innodb_limit_optimistic_insert_debug=2;
|
||||
INSERT INTO t1 VALUES (124),(125),(126),(127),(128),(129);
|
||||
}
|
||||
DELETE FROM t1 WHERE a>0;
|
||||
|
||||
--echo # Persist the state of the above incomplete transaction by
|
||||
@@ -107,12 +111,14 @@ SELECT * FROM t1;
|
||||
let SEARCH_PATTERN= syntax error in innodb_log_group_home_dir;
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
if ($have_debug) {
|
||||
--let $restart_parameters= --debug=d,innodb_log_abort_1
|
||||
--source include/restart_mysqld.inc
|
||||
--error ER_UNKNOWN_STORAGE_ENGINE
|
||||
SELECT * FROM t1;
|
||||
let SEARCH_PATTERN= InnoDB: Starting crash recovery from checkpoint LSN=.*;
|
||||
--source include/search_pattern_in_file.inc
|
||||
}
|
||||
|
||||
--let $restart_parameters= --innodb-read-only
|
||||
--source include/restart_mysqld.inc
|
||||
@@ -122,6 +128,7 @@ SELECT * FROM t1;
|
||||
let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery;
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
if ($have_debug) {
|
||||
--let $restart_parameters= --debug=d,innodb_log_abort_5
|
||||
--source include/restart_mysqld.inc
|
||||
--error ER_UNKNOWN_STORAGE_ENGINE
|
||||
@@ -135,6 +142,7 @@ let SEARCH_PATTERN= redo log from 5\\.000MiB to [0-9.]*[KMGT]iB;
|
||||
SELECT * FROM t1;
|
||||
let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery;
|
||||
--source include/search_pattern_in_file.inc
|
||||
}
|
||||
|
||||
# Trigger an error in recovery.
|
||||
|
||||
|
||||
@@ -3118,7 +3118,7 @@ re_evict:
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
buf_flush_sync();
|
||||
buf_flush_sync_batch(LSN_MAX);
|
||||
|
||||
state = block->page.state();
|
||||
|
||||
@@ -4090,15 +4090,15 @@ ATTRIBUTE_COLD void buf_pool_t::clear_hash_index() noexcept
|
||||
@retval nullptr if all freed */
|
||||
void buf_pool_t::assert_all_freed() noexcept
|
||||
{
|
||||
mysql_mutex_lock(&mutex);
|
||||
mysql_mutex_assert_owner(&mutex);
|
||||
|
||||
for (char *extent= memory,
|
||||
*end= memory + block_descriptors_in_bytes(n_blocks);
|
||||
extent < end; extent+= innodb_buffer_pool_extent_size)
|
||||
for (buf_block_t *block= reinterpret_cast<buf_block_t*>(extent),
|
||||
*extent_end= block +
|
||||
pages_in_extent[srv_page_size_shift - UNIV_PAGE_SIZE_SHIFT_MIN];
|
||||
block < extent_end && reinterpret_cast<char*>(block) < end; block++)
|
||||
for (char *extent= memory,
|
||||
*end= memory + block_descriptors_in_bytes(n_blocks);
|
||||
extent < end; extent+= innodb_buffer_pool_extent_size)
|
||||
for (buf_block_t *block= reinterpret_cast<buf_block_t*>(extent),
|
||||
*extent_end= block +
|
||||
pages_in_extent[srv_page_size_shift - UNIV_PAGE_SIZE_SHIFT_MIN];
|
||||
block < extent_end && reinterpret_cast<char*>(block) < end; block++)
|
||||
{
|
||||
if (!block->page.in_file())
|
||||
continue;
|
||||
@@ -4128,8 +4128,6 @@ void buf_pool_t::assert_all_freed() noexcept
|
||||
fixed_or_dirty:
|
||||
ib::fatal() << "Page " << block->page.id() << " still fixed or dirty";
|
||||
}
|
||||
|
||||
mysql_mutex_unlock(&mutex);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
@@ -4140,33 +4138,6 @@ void buf_refresh_io_stats() noexcept
|
||||
buf_pool.old_stat = buf_pool.stat;
|
||||
}
|
||||
|
||||
/** Invalidate all pages in the buffer pool.
|
||||
All pages must be in a replaceable state (not modified or latched). */
|
||||
void buf_pool_invalidate() noexcept
|
||||
{
|
||||
/* It is possible that a write batch that has been posted
|
||||
earlier is still not complete. For buffer pool invalidation to
|
||||
proceed we must ensure there is NO write activity happening. */
|
||||
|
||||
os_aio_wait_until_no_pending_writes(false);
|
||||
ut_d(buf_pool.assert_all_freed());
|
||||
mysql_mutex_lock(&buf_pool.mutex);
|
||||
|
||||
while (UT_LIST_GET_LEN(buf_pool.LRU)) {
|
||||
buf_LRU_scan_and_free_block();
|
||||
}
|
||||
|
||||
ut_ad(UT_LIST_GET_LEN(buf_pool.unzip_LRU) == 0);
|
||||
|
||||
buf_pool.freed_page_clock = 0;
|
||||
buf_pool.LRU_old = NULL;
|
||||
buf_pool.LRU_old_len = 0;
|
||||
buf_pool.stat.init();
|
||||
|
||||
buf_refresh_io_stats();
|
||||
mysql_mutex_unlock(&buf_pool.mutex);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Validate the buffer pool. */
|
||||
void buf_pool_t::validate() noexcept
|
||||
|
||||
@@ -173,9 +173,15 @@ fail:
|
||||
ut_ad(init_mtr.get_savepoint() == 1);
|
||||
ut_ad(init_mtr.m_memo[0].object == new_block);
|
||||
ut_ad(init_mtr.m_memo[0].type == MTR_MEMO_PAGE_X_MODIFY);
|
||||
new_block->page.fix();
|
||||
init_mtr.m_memo[0].type= MTR_MEMO_PAGE_X_FIX;
|
||||
init_mtr.rollback_to_savepoint(0, 1);
|
||||
init_mtr.m_log.erase();
|
||||
mysql_mutex_lock(&buf_pool.mutex);
|
||||
new_block->page.unfix();
|
||||
ut_d(bool freed=) buf_LRU_free_page(&new_block->page, true);
|
||||
ut_ad(freed);
|
||||
mysql_mutex_unlock(&buf_pool.mutex);
|
||||
|
||||
if (i == size / 2)
|
||||
ut_a(id.page_no() == size);
|
||||
@@ -202,11 +208,6 @@ fail:
|
||||
TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N);
|
||||
mtr.commit();
|
||||
|
||||
buf_flush_wait_flushed(mtr.commit_lsn());
|
||||
|
||||
/* Remove doublewrite pages from LRU */
|
||||
buf_pool_invalidate();
|
||||
|
||||
sql_print_information("InnoDB: Doublewrite buffer created");
|
||||
goto start_again;
|
||||
}
|
||||
|
||||
@@ -2057,8 +2057,7 @@ log file. Use log_make_checkpoint() to flush also the pool.
|
||||
@retval false if a checkpoint write was already running */
|
||||
static bool log_checkpoint() noexcept
|
||||
{
|
||||
if (recv_recovery_is_on())
|
||||
recv_sys.apply(true);
|
||||
ut_ad(!recv_recovery_is_on());
|
||||
|
||||
#if defined HAVE_valgrind && !__has_feature(memory_sanitizer)
|
||||
/* The built-in scheduler in Valgrind may neglect some threads for a
|
||||
@@ -2130,9 +2129,6 @@ ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn) noexcept
|
||||
ut_ad(sync_lsn < LSN_MAX);
|
||||
ut_ad(!srv_read_only_mode);
|
||||
|
||||
if (recv_recovery_is_on())
|
||||
recv_sys.apply(true);
|
||||
|
||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||
|
||||
if (buf_pool.get_oldest_modification(sync_lsn) < sync_lsn)
|
||||
@@ -2189,9 +2185,6 @@ ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious) noexcept
|
||||
{
|
||||
ut_ad(!srv_read_only_mode);
|
||||
|
||||
if (recv_recovery_is_on())
|
||||
recv_sys.apply(true);
|
||||
|
||||
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", return;);
|
||||
|
||||
Atomic_relaxed<lsn_t> &limit= furious
|
||||
@@ -2861,7 +2854,7 @@ ATTRIBUTE_COLD void buf_flush_buffer_pool() noexcept
|
||||
|
||||
/** 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) noexcept
|
||||
ATTRIBUTE_COLD void buf_flush_sync_batch(lsn_t lsn) noexcept
|
||||
{
|
||||
lsn= std::max(lsn, log_get_lsn());
|
||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||
@@ -2869,43 +2862,6 @@ void buf_flush_sync_batch(lsn_t lsn) noexcept
|
||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||
}
|
||||
|
||||
/** Synchronously flush dirty blocks.
|
||||
NOTE: The calling thread is not allowed to hold any buffer page latches! */
|
||||
void buf_flush_sync() noexcept
|
||||
{
|
||||
if (recv_recovery_is_on())
|
||||
{
|
||||
mysql_mutex_lock(&recv_sys.mutex);
|
||||
recv_sys.apply(true);
|
||||
mysql_mutex_unlock(&recv_sys.mutex);
|
||||
}
|
||||
|
||||
thd_wait_begin(nullptr, THD_WAIT_DISKIO);
|
||||
tpool::tpool_wait_begin();
|
||||
log_sys.latch.wr_lock(SRW_LOCK_CALL);
|
||||
|
||||
for (lsn_t lsn= log_sys.get_lsn();;)
|
||||
{
|
||||
log_sys.latch.wr_unlock();
|
||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||
buf_flush_wait(lsn);
|
||||
/* Wait for the page cleaner to be idle (for log resizing at startup) */
|
||||
while (buf_flush_sync_lsn)
|
||||
my_cond_wait(&buf_pool.done_flush_list,
|
||||
&buf_pool.flush_list_mutex.m_mutex);
|
||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||
log_sys.latch.wr_lock(SRW_LOCK_CALL);
|
||||
lsn_t new_lsn= log_sys.get_lsn();
|
||||
if (lsn == new_lsn)
|
||||
break;
|
||||
lsn= new_lsn;
|
||||
}
|
||||
|
||||
log_sys.latch.wr_unlock();
|
||||
tpool::tpool_wait_end();
|
||||
thd_wait_end(nullptr);
|
||||
}
|
||||
|
||||
ATTRIBUTE_COLD void buf_pool_t::print_flush_info() const noexcept
|
||||
{
|
||||
/* We do dirty read of UT_LIST count variable. */
|
||||
|
||||
@@ -18440,7 +18440,7 @@ buf_flush_list_now_set(THD*, st_mysql_sys_var*, void*, const void* save)
|
||||
os_aio_wait_until_no_pending_writes(true);
|
||||
}
|
||||
else
|
||||
buf_flush_sync();
|
||||
buf_flush_sync_batch(LSN_MAX);
|
||||
mysql_mutex_lock(&LOCK_global_system_variables);
|
||||
}
|
||||
|
||||
|
||||
@@ -400,10 +400,6 @@ buf_print_io(
|
||||
/** Refresh the statistics used to print per-second averages. */
|
||||
void buf_refresh_io_stats() noexcept;
|
||||
|
||||
/** Invalidate all pages in the buffer pool.
|
||||
All pages must be in a replaceable state (not modified or latched). */
|
||||
void buf_pool_invalidate() noexcept;
|
||||
|
||||
/*========================================================================
|
||||
--------------------------- LOWER LEVEL ROUTINES -------------------------
|
||||
=========================================================================*/
|
||||
|
||||
@@ -104,8 +104,4 @@ void buf_flush_validate() noexcept;
|
||||
|
||||
/** 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) noexcept;
|
||||
|
||||
/** Synchronously flush dirty blocks.
|
||||
NOTE: The calling thread is not allowed to hold any buffer page latches! */
|
||||
void buf_flush_sync() noexcept;
|
||||
ATTRIBUTE_COLD void buf_flush_sync_batch(lsn_t lsn) noexcept;
|
||||
|
||||
@@ -238,7 +238,10 @@ public:
|
||||
|
||||
/** whether we are applying redo log records during crash recovery.
|
||||
This can be cleared when holding mutex, or when pages.empty() and
|
||||
we are holding exclusive log_sys.latch. */
|
||||
we are holding exclusive log_sys.latch. When this is set,
|
||||
buf_flush_page_cleaner() will not invoke log_checkpoint_low(),
|
||||
buf_pool.flush_list may be unsorted by buf_page_t::oldest_modification(),
|
||||
and garbage_collect() replaces buf_pool_t::running_out(). */
|
||||
Atomic_relaxed<bool> recovery_on= false;
|
||||
/** whether recv_recover_page(), invoked from buf_page_t::read_complete(),
|
||||
should apply log records*/
|
||||
|
||||
@@ -1515,7 +1515,9 @@ wait_suspend_loop:
|
||||
|
||||
service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL,
|
||||
"Free innodb buffer pool");
|
||||
ut_d(mysql_mutex_lock(&buf_pool.mutex));
|
||||
ut_d(buf_pool.assert_all_freed());
|
||||
ut_d(mysql_mutex_unlock(&buf_pool.mutex));
|
||||
|
||||
ut_a(lsn == log_get_lsn()
|
||||
|| srv_force_recovery == SRV_FORCE_NO_LOG_REDO);
|
||||
|
||||
@@ -4091,6 +4091,30 @@ static void log_sort_flush_list() noexcept
|
||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||
}
|
||||
|
||||
/** Invalidate all pages in the buffer pool.
|
||||
All pages must be replaceable (not modified, latched, or io-fixed). */
|
||||
ATTRIBUTE_COLD static void buf_pool_invalidate() noexcept
|
||||
{
|
||||
mysql_mutex_lock(&buf_pool.mutex);
|
||||
ut_ad(!os_aio_pending_reads());
|
||||
/* os_aio_pending_writes() may hold here if some write_io_callback()
|
||||
did not release the slot yet. However, buf_flush_sync_batch() waited
|
||||
for the page write itself to complete, which we will check below. */
|
||||
ut_d(buf_pool.assert_all_freed());
|
||||
|
||||
while (UT_LIST_GET_LEN(buf_pool.LRU))
|
||||
buf_LRU_scan_and_free_block();
|
||||
|
||||
ut_ad(UT_LIST_GET_LEN(buf_pool.unzip_LRU) == 0);
|
||||
|
||||
buf_pool.freed_page_clock= 0;
|
||||
buf_pool.LRU_old= nullptr;
|
||||
buf_pool.LRU_old_len= 0;
|
||||
buf_pool.stat.init();
|
||||
buf_refresh_io_stats();
|
||||
mysql_mutex_unlock(&buf_pool.mutex);
|
||||
}
|
||||
|
||||
/** Apply buffered log to persistent data pages.
|
||||
@param last_batch whether it is possible to write more redo log */
|
||||
void recv_sys_t::apply(bool last_batch)
|
||||
|
||||
@@ -171,7 +171,9 @@ static void delete_log_files()
|
||||
@return DB_SUCCESS or error code */
|
||||
static dberr_t create_log_file(bool create_new_db, lsn_t lsn)
|
||||
{
|
||||
ut_ad(log_sys.latch_have_wr());
|
||||
ut_ad(!srv_read_only_mode);
|
||||
ut_ad(!buf_pool.get_oldest_modification(0));
|
||||
|
||||
/* We will retain ib_logfile0 until we have written a new logically
|
||||
empty log as ib_logfile101 and atomically renamed it to
|
||||
@@ -179,9 +181,6 @@ static dberr_t create_log_file(bool create_new_db, lsn_t lsn)
|
||||
delete_log_files();
|
||||
|
||||
ut_ad(!os_aio_pending_reads());
|
||||
ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex));
|
||||
ut_ad(!buf_pool.get_oldest_modification(0));
|
||||
ut_d(mysql_mutex_unlock(&buf_pool.flush_list_mutex));
|
||||
/* os_aio_pending_writes() may hold here if some
|
||||
write_io_callback() did not release the slot yet. However,
|
||||
the page write itself must have completed, because the
|
||||
@@ -190,7 +189,6 @@ static dberr_t create_log_file(bool create_new_db, lsn_t lsn)
|
||||
assumption does not hold. */
|
||||
ut_d(os_aio_wait_until_no_pending_writes(false));
|
||||
|
||||
log_sys.latch.wr_lock(SRW_LOCK_CALL);
|
||||
log_sys.set_capacity();
|
||||
|
||||
std::string logfile0{get_log_file_path("ib_logfile101")};
|
||||
@@ -206,6 +204,7 @@ static dberr_t create_log_file(bool create_new_db, lsn_t lsn)
|
||||
int(logfile0.size()), logfile0.data());
|
||||
err_exit:
|
||||
log_sys.latch.wr_unlock();
|
||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||
return DB_ERROR;
|
||||
}
|
||||
|
||||
@@ -223,14 +222,6 @@ close_and_exit:
|
||||
goto close_and_exit;
|
||||
}
|
||||
|
||||
mysql_mutex_lock(&recv_sys.mutex);
|
||||
const bool all_opened = fil_system.sys_space->open(create_new_db);
|
||||
mysql_mutex_unlock(&recv_sys.mutex);
|
||||
|
||||
if (!all_opened) {
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
/* Create a log checkpoint. */
|
||||
if (log_sys.is_encrypted() && !log_crypt_init()) {
|
||||
goto err_exit;
|
||||
@@ -255,6 +246,7 @@ close_and_exit:
|
||||
buf_page_t::read_complete(). */
|
||||
recv_sys.recovery_on = false;
|
||||
log_sys.latch.wr_unlock();
|
||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||
|
||||
log_make_checkpoint();
|
||||
log_buffer_flush_to_disk();
|
||||
@@ -1068,15 +1060,19 @@ srv_init_abort_low(
|
||||
|
||||
/** Prepare to delete the redo log file. Flush the dirty pages from all the
|
||||
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() noexcept
|
||||
@return lsn upto which data pages have been flushed and log_sys.latch acquired
|
||||
@retval 0 in case of error; log_sys.latch will not be acquired */
|
||||
static ATTRIBUTE_COLD lsn_t srv_prepare_to_delete_redo_log_file() noexcept
|
||||
{
|
||||
DBUG_ENTER("srv_prepare_to_delete_redo_log_file");
|
||||
|
||||
mysql_mutex_lock(&recv_sys.mutex);
|
||||
ut_ad(recv_sys.recovery_on);
|
||||
recv_sys.apply(true);
|
||||
mysql_mutex_unlock(&recv_sys.mutex);
|
||||
|
||||
/* Clean the buffer pool. */
|
||||
buf_flush_sync();
|
||||
buf_flush_sync_batch(LSN_MAX);
|
||||
|
||||
DBUG_EXECUTE_IF("innodb_log_abort_1", DBUG_RETURN(0););
|
||||
DBUG_PRINT("ib_log", ("After innodb_log_abort_1"));
|
||||
@@ -1085,21 +1081,6 @@ static lsn_t srv_prepare_to_delete_redo_log_file() noexcept
|
||||
const bool latest_format{log_sys.is_latest()};
|
||||
lsn_t flushed_lsn{log_sys.get_flushed_lsn(std::memory_order_relaxed)};
|
||||
|
||||
if (latest_format && !(log_sys.file_size & 4095) &&
|
||||
flushed_lsn != log_sys.next_checkpoint_lsn +
|
||||
(log_sys.is_encrypted()
|
||||
? SIZE_OF_FILE_CHECKPOINT + 8
|
||||
: SIZE_OF_FILE_CHECKPOINT))
|
||||
{
|
||||
#ifdef HAVE_PMEM
|
||||
if (!log_sys.is_opened())
|
||||
log_sys.buf_size= unsigned(std::min<uint64_t>(log_sys.capacity(),
|
||||
log_sys.buf_size_max));
|
||||
#endif
|
||||
fil_names_clear(flushed_lsn);
|
||||
flushed_lsn= log_sys.get_lsn();
|
||||
}
|
||||
|
||||
{
|
||||
const char *msg;
|
||||
if (!latest_format)
|
||||
@@ -1131,18 +1112,6 @@ same_size:
|
||||
}
|
||||
}
|
||||
|
||||
log_sys.latch.wr_unlock();
|
||||
|
||||
if (latest_format)
|
||||
log_write_up_to(flushed_lsn, false);
|
||||
|
||||
ut_ad(flushed_lsn == log_get_lsn());
|
||||
ut_ad(!os_aio_pending_reads());
|
||||
ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex));
|
||||
ut_ad(!buf_pool.get_oldest_modification(0));
|
||||
ut_d(mysql_mutex_unlock(&buf_pool.flush_list_mutex));
|
||||
ut_d(os_aio_wait_until_no_pending_writes(false));
|
||||
|
||||
DBUG_RETURN(flushed_lsn);
|
||||
}
|
||||
|
||||
@@ -1381,6 +1350,8 @@ dberr_t srv_start(bool create_new_db)
|
||||
|
||||
if (create_new_db) {
|
||||
lsn_t flushed_lsn = log_sys.init_lsn();
|
||||
log_sys.latch.wr_lock(SRW_LOCK_CALL);
|
||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||
|
||||
err = create_log_file(true, flushed_lsn);
|
||||
|
||||
@@ -1470,8 +1441,6 @@ dberr_t srv_start(bool create_new_db)
|
||||
return(srv_init_abort(err));
|
||||
}
|
||||
|
||||
buf_flush_sync();
|
||||
|
||||
ut_ad(!srv_log_file_created);
|
||||
ut_d(srv_log_file_created= true);
|
||||
|
||||
@@ -1578,17 +1547,16 @@ dberr_t srv_start(bool create_new_db)
|
||||
} else {
|
||||
/* Prepare to delete the old redo log file */
|
||||
const lsn_t lsn{srv_prepare_to_delete_redo_log_file()};
|
||||
|
||||
DBUG_EXECUTE_IF("innodb_log_abort_1",
|
||||
return(srv_init_abort(DB_ERROR)););
|
||||
if (!lsn) {
|
||||
return srv_init_abort(DB_ERROR);
|
||||
}
|
||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||
ut_ad(!buf_pool.get_oldest_modification(0));
|
||||
/* Prohibit redo log writes from any other
|
||||
threads until creating a log checkpoint at the
|
||||
end of create_log_file(). */
|
||||
ut_d(recv_no_log_write = true);
|
||||
ut_ad(!os_aio_pending_reads());
|
||||
ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex));
|
||||
ut_ad(!buf_pool.get_oldest_modification(0));
|
||||
ut_d(mysql_mutex_unlock(&buf_pool.flush_list_mutex));
|
||||
/* os_aio_pending_writes() may hold here if
|
||||
some write_io_callback() did not release the
|
||||
slot yet. However, the page write itself must
|
||||
@@ -1602,6 +1570,9 @@ dberr_t srv_start(bool create_new_db)
|
||||
log_sys.close_file();
|
||||
|
||||
DBUG_EXECUTE_IF("innodb_log_abort_5",
|
||||
log_sys.latch.wr_unlock();
|
||||
mysql_mutex_unlock(
|
||||
&buf_pool.flush_list_mutex);
|
||||
return(srv_init_abort(DB_ERROR)););
|
||||
DBUG_PRINT("ib_log", ("After innodb_log_abort_5"));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user