/* Flags that tell the buffer pool dump/load thread which action should it
take after being waked up. */ staticvolatilebool buf_dump_should_start; staticvolatilebool buf_load_should_start;
static Atomic_relaxed<bool> buf_load_abort_flag;
/** Start the buffer pool dump/load task and instructs it to start a dump. */ void buf_dump_start()
{
buf_dump_should_start= true;
buf_do_load_dump();
}
/** Start the buffer pool dump/load task and instructs it to start a load. */ void buf_load_start()
{
buf_load_should_start= true;
buf_do_load_dump();
}
/*****************************************************************//**
Sets the global variable that feeds MySQL's innodb_buffer_pool_dump_status
to the specified string. The format and the following parameters are the
same as the ones used for printf(3). The value of this variable can be
retrieved by:
SELECT variable_value FROM information_schema.global_status WHERE
variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS'; or by:
SHOW STATUS LIKE 'innodb_buffer_pool_dump_status'; */ static MY_ATTRIBUTE((nonnull, format(printf, 2, 3))) void
buf_dump_status( /*============*/ enum status_severity severity,/*!< in: status severity */ constchar* fmt, /*!< in: format */
...) /*!< in: extra parameters according
to fmt */
{
va_list ap;
switch (severity) { case STATUS_INFO:
ib::info() << export_vars.innodb_buffer_pool_dump_status; break;
case STATUS_ERR:
ib::error() << export_vars.innodb_buffer_pool_dump_status; break;
}
va_end(ap);
}
/*****************************************************************//**
Sets the global variable that feeds MySQL's innodb_buffer_pool_load_status
to the specified string. The format and the following parameters are the
same as the ones used for printf(3). The value of this variable can be
retrieved by:
SELECT variable_value FROM information_schema.global_status WHERE
variable_name = 'INNODB_BUFFER_POOL_LOAD_STATUS'; or by:
SHOW STATUS LIKE 'innodb_buffer_pool_load_status'; */ static MY_ATTRIBUTE((nonnull, format(printf, 2, 3))) void
buf_load_status( /*============*/ enum status_severity severity,/*!< in: status severity */ constchar* fmt, /*!< in: format */
...) /*!< in: extra parameters according to fmt */
{
va_list ap;
switch (severity) { case STATUS_INFO:
ib::info() << export_vars.innodb_buffer_pool_load_status; break;
case STATUS_ERR:
ib::error() << export_vars.innodb_buffer_pool_load_status; break;
}
va_end(ap);
}
/** Returns the directory path where the buffer pool dump file will be created.
@return directory path */ static constchar*
get_buf_dump_dir()
{ constchar* dump_dir;
/* The dump file should be created in the default data directory if
innodb_data_home_dir is set as an empty string. */ if (!*srv_data_home) {
dump_dir = fil_path_to_mysql_datadir;
} else {
dump_dir = srv_data_home;
}
return(dump_dir);
}
/** Generate the path to the buffer pool dump/load file. @param[out]pathgeneratedpath
@param[in] path_size size of 'path', used as in snprintf(3). */ staticvoid buf_dump_generate_path(char *path, size_t path_size)
{ char buf[FN_REFLEN];
/* For realpath() to succeed the file must exist. */
if (ret && exists) { /* my_realpath() assumes the destination buffer is big enough
to hold FN_REFLEN bytes. */
ut_a(path_size >= FN_REFLEN);
my_realpath(path, buf, 0);
} else { /* If it does not exist, then resolve only srv_data_home
and append srv_buf_dump_filename to it. */ char srv_data_home_full[FN_REFLEN];
snprintf(path, path_size, format,
srv_data_home_full, srv_buf_dump_filename);
}
}
/*****************************************************************//**
Perform a buffer pool dump into the file specified by
innodb_buffer_pool_filename. If any errors occur then the value of
innodb_buffer_pool_dump_status will be set accordingly, see buf_dump_status().
The dump filename can be specified by (relative to srv_data_home):
SET GLOBAL innodb_buffer_pool_filename='filename'; */ static void
buf_dump( /*=====*/
ibool obey_shutdown) /*!< in: quit if we are in a shutting down
state */
{ #define SHOULD_QUIT() (SHUTTING_DOWN() && obey_shutdown)
if (srv_buf_pool_dump_pct != 100) {
ulint t_pages;
/* limit the number of total pages dumped to X% of the
total number of pages */
t_pages = buf_pool.curr_size() * srv_buf_pool_dump_pct / 100; if (n_pages > t_pages) {
buf_dump_status(STATUS_INFO, "Restricted to " ULINTPF " pages due to " "innodb_buf_pool_dump_pct=%lu",
t_pages, srv_buf_pool_dump_pct);
n_pages = t_pages;
}
if (id.space() == SRV_TMP_SPACE_ID) { /* Ignore the innodb_temporary tablespace. */ continue;
}
dump[j++] = id;
}
mysql_mutex_unlock(&buf_pool.mutex);
ut_a(j <= n_pages);
n_pages = j;
for (j = 0; j < n_pages && !SHOULD_QUIT(); j++) {
ret = fprintf(f, "%u,%u\n",
dump[j].space(), dump[j].page_no()); if (ret < 0) {
ut_free(dump);
fclose(f);
buf_dump_status(STATUS_ERR, "Cannot write to '%s': %s",
tmp_filename, strerror(errno)); /* leave tmp_filename to exist */ return;
} if (SHUTTING_DOWN() && !(j & 1023)) {
service_manager_extend_timeout(
INNODB_EXTEND_TIMEOUT_INTERVAL, "Dumping buffer pool page "
ULINTPF "/" ULINTPF, j + 1, n_pages);
}
}
ut_free(dump);
done:
ret = IF_WIN(my_fclose(f,0),fclose(f)); if (ret != 0) {
buf_dump_status(STATUS_ERR, "Cannot close '%s': %s",
tmp_filename, strerror(errno)); return;
} /* else */
ret = unlink(full_filename); if (ret != 0 && errno != ENOENT) {
buf_dump_status(STATUS_ERR, "Cannot delete '%s': %s",
full_filename, strerror(errno)); /* leave tmp_filename to exist */ return;
} /* else */
ret = rename(tmp_filename, full_filename); if (ret != 0) {
buf_dump_status(STATUS_ERR, "Cannot rename '%s' to '%s': %s",
tmp_filename, full_filename,
strerror(errno)); /* leave tmp_filename to exist */ return;
} /* else */
/* success */
ut_sprintf_timestamp(now, sizeof(now));
buf_dump_status(STATUS_INFO, "Buffer pool(s) dump completed at %s", now);
/* Though dumping doesn't related to an incomplete load, weresetthisto0heretoindicatethatashutdowncanalsoperform
a dump */
export_vars.innodb_buffer_pool_load_incomplete = 0;
}
/*****************************************************************//**
Perform a buffer pool load from the file specified by
innodb_buffer_pool_filename. If any errors occur then the value of
innodb_buffer_pool_load_status will be set accordingly, see buf_load_status().
The dump filename can be specified by (relative to srv_data_home):
SET GLOBAL innodb_buffer_pool_filename='filename'; */ static void
buf_load() /*======*/
{ char full_filename[OS_FILE_MAX_PATH]; char now[32];
FILE* f;
page_id_t* dump;
ulint dump_n;
ulint i;
uint32_t space_id;
uint32_t page_no; int fscanf_ret;
/* Ignore any leftovers from before */
buf_load_abort_flag = false;
buf_load_status(STATUS_INFO, "Loading buffer pool(s) from %s", full_filename);
f = fopen(full_filename, "r" STR_O_CLOEXEC); if (f == NULL) {
buf_load_status(STATUS_INFO, "Cannot open '%s' for reading: %s",
full_filename, strerror(errno)); return;
} /* else */
/* First scan the file to estimate how many entries are in it. Thisfileistiny(approx500KBper1GBbufferpool),readingit
two times is fine. */
dump_n = 0; while (fscanf(f, "%u,%u", &space_id, &page_no) == 2
&& !SHUTTING_DOWN()) {
dump_n++;
}
if (!SHUTTING_DOWN() && !feof(f)) { /* fscanf() returned != 2 */ constchar* what; if (ferror(f)) {
what = "reading";
} else {
what = "parsing";
}
fclose(f);
buf_load_status(STATUS_ERR, "Error %s '%s'," " unable to load buffer pool (stage 1)",
what, full_filename); return;
}
/* If the dump is larger than the buffer pool, then we ignore the extratrailing.Thiscouldhappenifadumpismade,thenbuffer
pool is shrunk and then load is attempted. */
dump_n = std::min(dump_n, buf_pool.curr_size());
for (i = 0; i < dump_n && !SHUTTING_DOWN(); i++) {
fscanf_ret = fscanf(f, "%u,%u", &space_id, &page_no);
if (fscanf_ret != 2) { if (feof(f)) { break;
} /* else */
ut_free(dump);
fclose(f);
buf_load_status(STATUS_ERR, "Error parsing '%s', unable" " to load buffer pool (stage 2)",
full_filename); return;
}
if (space_id > ULINT32_MASK || page_no > ULINT32_MASK) {
ut_free(dump);
fclose(f);
buf_load_status(STATUS_ERR, "Error parsing '%s': bogus" " space,page %u,%u at line " ULINTPF ", unable to load buffer pool",
full_filename,
space_id, page_no,
i); return;
}
dump[i] = page_id_t(space_id, page_no);
}
/* Set dump_n to the actual number of initialized elements, icouldbesmallerthandump_nhereifthefilegottruncatedafter
we read it the first time. */
dump_n = i;
fclose(f);
if (dump_n == 0) {
ut_free(dump);
ut_sprintf_timestamp(now, sizeof(now));
buf_load_status(STATUS_INFO, "Buffer pool(s) load completed at %s" " (%s was empty or had errors)", now, full_filename); return;
}
if (!SHUTTING_DOWN()) {
std::sort(dump, dump + dump_n);
std::set<uint32_t> missing; for (const page_id_t id : st_::span<const page_id_t>
(dump, dump_n)) {
missing.emplace(id.space());
} for (std::set<uint32_t>::iterator i = missing.begin();
i != missing.end(); ) { auto j = i++; if (fil_space_t* space = fil_space_t::get(*j)) {
space->release();
missing.erase(j);
}
} if (!missing.empty()) {
dict_load_tablespaces(&missing);
}
}
/* Avoid calling the expensive fil_space_t::get() for each pagewithinthesametablespace.dump[]issortedby(space,page),
so all pages from a given tablespace are consecutive. */
uint32_t cur_space_id = dump[0].space();
fil_space_t* space = fil_space_t::get(cur_space_id);
for (i = 0; i < dump_n && !SHUTTING_DOWN(); i++) {
/* space_id for this iteration of the loop */ const uint32_t this_space_id = dump[i].space();
if (this_space_id >= SRV_SPACE_ID_UPPER_BOUND) { continue;
}
if (this_space_id != cur_space_id) { if (space) {
space->release();
}
cur_space_id = this_space_id;
space = fil_space_t::get(cur_space_id);
}
/* JAN: TODO: As we use background page read below,
if tablespace is encrypted we cant use it. */ if (!space || dump[i].page_no() >= space->get_size() ||
(space->crypt_data &&
space->crypt_data->encryption != FIL_ENCRYPTION_OFF &&
space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED)) { continue;
}
if (space->is_stopping()) {
space->release();
space = nullptr; continue;
}
if (buf_load_abort_flag) { if (space) {
space->release();
}
buf_load_abort_flag = false;
ut_free(dump);
buf_load_status(
STATUS_INFO, "Buffer pool(s) load aborted on request"); /* Premature end, set estimated = completed = i and
end the current stage event. */
if (i == dump_n) {
buf_load_status(STATUS_INFO, "Buffer pool(s) load completed at %s", now);
export_vars.innodb_buffer_pool_load_incomplete = 0;
} elseif (!buf_load_abort_flag) {
buf_load_status(STATUS_INFO, "Buffer pool(s) load aborted due to user instigated abort at %s",
now); /* intentionally don't reset innodb_buffer_pool_load_incomplete
as we don't want a shutdown to save the buffer pool */
} else {
buf_load_status(STATUS_INFO, "Buffer pool(s) load aborted due to shutdown at %s",
now); /* intentionally don't reset innodb_buffer_pool_load_incomplete
as we want to abort without saving the buffer pool */
}
/* Make sure that estimated = completed when we end. */
mysql_stage_set_work_completed(pfs_stage_progress, dump_n); /* End the stage progress event. */
mysql_end_stage();
}
/** Abort a currently running buffer pool load. */ void buf_load_abort()
{
buf_load_abort_flag= true;
}
/*****************************************************************//** This is the main task for buffer pool dump/load. when scheduled
either performs a dump or load, depending on server state, state of the variables etc- */ staticvoid buf_dump_load_func(void *)
{
ut_ad(!srv_read_only_mode); staticbool first_time = true; if (first_time && srv_buffer_pool_load_at_startup) {
while (!SHUTTING_DOWN()) { if (buf_dump_should_start) {
buf_dump_should_start = false;
buf_dump(true);
} if (buf_load_should_start) {
buf_load_should_start = false;
buf_load();
}
if (!buf_dump_should_start && !buf_load_should_start) { return;
}
}
/* In shutdown */ if (srv_buffer_pool_dump_at_shutdown && srv_fast_shutdown != 2) { if (export_vars.innodb_buffer_pool_load_incomplete) {
buf_dump_status(STATUS_INFO, "Dumping of buffer pool not started" " as load was incomplete"); #ifdef WITH_WSREP
} elseif (get_wsrep_recovery()) { #endif/* WITH_WSREP */
} else {
buf_dump(false/* do complete dump at shutdown */);
}
}
}
/** Start async buffer pool load, if srv_buffer_pool_load_at_startup was set.*/ void buf_load_at_startup()
{
load_dump_enabled= true; if (srv_buffer_pool_load_at_startup)
buf_do_load_dump();
}
staticvoid buf_do_load_dump()
{ if (load_dump_enabled && !buf_dump_load_task.is_running())
srv_thread_pool->submit_task(&buf_dump_load_task);
}
/** Wait for currently running load/dumps to finish*/ void buf_load_dump_end()
{
ut_ad(SHUTTING_DOWN());
buf_dump_load_task.wait();
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.