# should be done or reviewed by the maintainer!
--- a/storage/innobase/buf/buf0lru.c
+++ b/storage/innobase/buf/buf0lru.c
-@@ -2167,6 +2167,284 @@
+@@ -2197,6 +2197,289 @@
memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur);
}
+ " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
+ goto end;
+ }
++
++ ut_print_timestamp(stderr);
++ fprintf(stderr, " InnoDB: Restoring buffer pool pages from %s\n",
++ LRU_DUMP_FILE);
++
+ if (size == 0 || size_high > 0 || size % 8) {
+ fprintf(stderr, " InnoDB: broken LRU dump file\n");
+ goto end;
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
-+ " InnoDB: reading pages based on the dumped LRU list was done."
++ " InnoDB: Completed reading buffer pool pages"
+ " (requested: %lu, read: %lu)\n", req, reads);
+ ret = TRUE;
+end:
Validates the LRU list for one buffer pool instance. */
--- a/storage/innobase/buf/buf0rea.c
+++ b/storage/innobase/buf/buf0rea.c
-@@ -58,7 +58,7 @@
+@@ -60,7 +60,7 @@
which case it is never read into the pool, or if the tablespace does
not exist or is being dropped
@return 1 if read request is issued. 0 if it is not */
/*==============*/
--- a/storage/innobase/fil/fil0fil.c
+++ b/storage/innobase/fil/fil0fil.c
-@@ -5290,6 +5290,70 @@
+@@ -5307,6 +5307,70 @@
return(DB_SUCCESS);
}
Waits for an aio operation to complete. This function is used to write the
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -11809,6 +11809,12 @@
+@@ -196,6 +196,8 @@
+
+ static char* innodb_version_str = (char*) INNODB_VERSION_STR;
+
++static my_bool innobase_blocking_lru_restore = FALSE;
++
+ /** Possible values for system variable "innodb_stats_method". The values
+ are defined the same as its corresponding MyISAM system variable
+ "myisam_stats_method"(see "myisam_stats_method_names"), for better usability */
+@@ -2652,6 +2654,8 @@
+ srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
+ srv_use_checksums = (ibool) innobase_use_checksums;
+
++ srv_blocking_lru_restore = (ibool) innobase_blocking_lru_restore;
++
+ #ifdef HAVE_LARGE_PAGES
+ if ((os_use_large_pages = (ibool) my_use_large_pages))
+ os_large_page_size = (ulint) opt_large_page_size;
+@@ -11964,6 +11968,19 @@
"Limit the allocated memory for dictionary cache. (0: unlimited)",
NULL, NULL, 0, 0, LONG_MAX, 0);
+ "Time in seconds between automatic buffer pool dumps. "
+ "0 (the default) disables automatic dumps.",
+ NULL, NULL, 0, 0, UINT_MAX32, 0);
++
++static MYSQL_SYSVAR_BOOL(blocking_buffer_pool_restore,
++ innobase_blocking_lru_restore,
++ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
++ "Block XtraDB startup process until buffer pool is full restored from a "
++ "dump file (if present). Disabled by default.",
++ NULL, NULL, FALSE);
+
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(additional_mem_pool_size),
MYSQL_SYSVAR(autoextend_increment),
-@@ -11891,6 +11897,7 @@
- #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+@@ -12048,6 +12065,8 @@
+ MYSQL_SYSVAR(random_read_ahead),
MYSQL_SYSVAR(read_ahead_threshold),
MYSQL_SYSVAR(io_capacity),
+ MYSQL_SYSVAR(buffer_pool_restore_at_startup),
++ MYSQL_SYSVAR(blocking_buffer_pool_restore),
MYSQL_SYSVAR(purge_threads),
MYSQL_SYSVAR(purge_batch_size),
MYSQL_SYSVAR(rollback_segments),
}
#define OK(expr) \
-@@ -4270,6 +4271,36 @@
+@@ -4336,6 +4337,36 @@
"Hello!");
goto end_func;
}
+buf_LRU_file_restore(void);
+/*======================*/
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- /**********************************************************************//**
+ /******************************************************************//**
+ Remove one page from LRU list and put it to free list */
--- a/storage/innobase/include/buf0rea.h
+++ b/storage/innobase/include/buf0rea.h
@@ -31,6 +31,37 @@
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
-@@ -644,6 +644,14 @@
+@@ -653,6 +653,14 @@
void* message, /*!< in: message for aio handler if non-sync
aio used, else ignored */
trx_t* trx);
handler for completed requests. The aio array of pending requests is divided
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
-@@ -356,6 +356,9 @@
+@@ -364,6 +364,12 @@
reading of a disk page */
extern ulint srv_buf_pool_reads;
+/** Time in seconds between automatic buffer pool dumps */
+extern uint srv_auto_lru_dump;
++
++/** Whether startup should be blocked until buffer pool is fully restored */
++extern ibool srv_blocking_lru_restore;
+
/** Status variables to be passed to MySQL */
typedef struct export_var_struct export_struc;
-@@ -661,6 +664,16 @@
+@@ -669,6 +675,16 @@
/*=====================*/
void* arg); /*!< in: a dummy parameter required by
os_thread_create */
@return FALSE if not all information printed
--- a/storage/innobase/srv/srv0srv.c
+++ b/storage/innobase/srv/srv0srv.c
-@@ -330,6 +330,9 @@
+@@ -332,6 +332,12 @@
reading of a disk page */
UNIV_INTERN ulint srv_buf_pool_reads = 0;
+/** Time in seconds between automatic buffer pool dumps */
+UNIV_INTERN uint srv_auto_lru_dump = 0;
++
++/** Whether startup should be blocked until buffer pool is fully restored */
++UNIV_INTERN ibool srv_blocking_lru_restore;
+
/* structure to pass status variables to MySQL */
UNIV_INTERN export_struc export_vars;
-@@ -2706,6 +2709,56 @@
- OS_THREAD_DUMMY_RETURN;
- }
+@@ -2708,6 +2714,58 @@
+ /* We count the number of threads in os_thread_exit(). A created
+ thread should always use that to exit and not use return() to exit. */
++ os_thread_exit(NULL);
++
++ OS_THREAD_DUMMY_RETURN;
++}
++
+/*********************************************************************//**
+A thread which restores the buffer pool from a dump file on startup and does
+periodic buffer pool dumps.
+ os_thread_pf(os_thread_get_curr_id()));
+#endif
+
-+ if (srv_auto_lru_dump)
++ /* If srv_blocking_lru_restore is TRUE, restore will be done
++ synchronously on startup. */
++ if (srv_auto_lru_dump && !srv_blocking_lru_restore)
+ buf_LRU_file_restore();
+
+ last_dump_time = time(NULL);
+ /* We count the number of threads in os_thread_exit(). A created
+ thread should always use that to exit and not use return() to exit. */
+
-+ os_thread_exit(NULL);
-+
-+ OS_THREAD_DUMMY_RETURN;
-+}
-+
- /**********************************************************************//**
- Check whether any background thread is active.
- @return FALSE if all are are suspended or have exited. */
+ os_thread_exit(NULL);
+
+ OS_THREAD_DUMMY_RETURN;
--- a/storage/innobase/srv/srv0start.c
+++ b/storage/innobase/srv/srv0start.c
-@@ -120,9 +120,9 @@
+@@ -87,6 +87,7 @@
+ # include "btr0pcur.h"
+ # include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
+ # include "zlib.h" /* for ZLIB_VERSION */
++# include "buf0lru.h" /* for buf_LRU_file_restore() */
+
+ /** Log sequence number immediately after startup */
+ UNIV_INTERN ib_uint64_t srv_start_lsn;
+@@ -120,9 +121,9 @@
static os_file_t files[1000];
/** io_handler_thread parameters for thread identification */
/** We use this mutex to test the return value of pthread_mutex_trylock
on successful locking. HP-UX does NOT return 0, though Linux et al do. */
-@@ -1821,6 +1821,10 @@
+@@ -1841,6 +1842,15 @@
os_thread_create(&srv_monitor_thread, NULL,
thread_ids + 4 + SRV_MAX_N_IO_THREADS);
+ /* Create the thread which automaticaly dumps/restore buffer pool */
+ os_thread_create(&srv_LRU_dump_restore_thread, NULL,
+ thread_ids + 5 + SRV_MAX_N_IO_THREADS);
++
++ /* If srv_blocking_lru_restore is TRUE, load buffer pool contents
++ synchronously */
++ if (srv_auto_lru_dump && srv_blocking_lru_restore)
++ buf_LRU_file_restore();
+
srv_is_being_started = FALSE;
err = dict_create_or_check_foreign_constraint_tables();
+--- /dev/null
++++ b/mysql-test/suite/sys_vars/r/innodb_blocking_buffer_pool_restore_basic.result
+@@ -0,0 +1,3 @@
++SELECT @@global.innodb_blocking_buffer_pool_restore;
++@@global.innodb_blocking_buffer_pool_restore
++0
+--- /dev/null
++++ b/mysql-test/suite/sys_vars/t/innodb_blocking_buffer_pool_restore_basic.test
+@@ -0,0 +1 @@
++SELECT @@global.innodb_blocking_buffer_pool_restore;