]> git.pld-linux.org Git - packages/mysql.git/blame - innodb_lru_dump_restore.patch
- added link patch (fixes build with systemtap probes)
[packages/mysql.git] / innodb_lru_dump_restore.patch
CommitLineData
b4e1fa2c
AM
1# name : innodb_lru_dump_restore.patch
2# introduced : 11 or before
3# maintainer : Yasufumi
4#
5#!!! notice !!!
6# Any small change to this file in the main branch
7# should be done or reviewed by the maintainer!
db82db79
AM
8--- a/storage/innobase/buf/buf0lru.c
9+++ b/storage/innobase/buf/buf0lru.c
29ffd636 10@@ -2197,6 +2197,289 @@
b4e1fa2c
AM
11 memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur);
12 }
13
14+/********************************************************************//**
15+Dump the LRU page list to the specific file. */
16+#define LRU_DUMP_FILE "ib_lru_dump"
17+
18+UNIV_INTERN
19+ibool
20+buf_LRU_file_dump(void)
21+/*===================*/
22+{
23+ os_file_t dump_file = -1;
24+ ibool success;
25+ byte* buffer_base = NULL;
26+ byte* buffer = NULL;
27+ buf_page_t* bpage;
28+ ulint buffers;
29+ ulint offset;
30+ ibool ret = FALSE;
31+ ulint i;
32+
33+ for (i = 0; i < srv_n_data_files; i++) {
34+ if (strstr(srv_data_file_names[i], LRU_DUMP_FILE) != NULL) {
35+ fprintf(stderr,
36+ " InnoDB: The name '%s' seems to be used for"
d8778560
AM
37+ " innodb_data_file_path. For safety, dumping of the LRU list"
38+ " is not being done.\n", LRU_DUMP_FILE);
b4e1fa2c
AM
39+ goto end;
40+ }
41+ }
42+
43+ buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE);
44+ buffer = ut_align(buffer_base, UNIV_PAGE_SIZE);
45+ if (!buffer) {
46+ fprintf(stderr,
47+ " InnoDB: cannot allocate buffer.\n");
48+ goto end;
49+ }
50+
51+ dump_file = os_file_create(innodb_file_temp_key, LRU_DUMP_FILE, OS_FILE_OVERWRITE,
52+ OS_FILE_NORMAL, OS_DATA_FILE, &success);
53+ if (!success) {
54+ os_file_get_last_error(TRUE);
55+ fprintf(stderr,
56+ " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
57+ goto end;
58+ }
59+
60+ buffers = offset = 0;
61+
62+ for (i = 0; i < srv_buf_pool_instances; i++) {
63+ buf_pool_t* buf_pool;
64+
65+ buf_pool = buf_pool_from_array(i);
66+
67+ mutex_enter(&buf_pool->LRU_list_mutex);
68+ bpage = UT_LIST_GET_LAST(buf_pool->LRU);
69+
70+ while (bpage != NULL) {
71+ if (offset == 0) {
72+ memset(buffer, 0, UNIV_PAGE_SIZE);
73+ }
74+
75+ mach_write_to_4(buffer + offset * 4, bpage->space);
76+ offset++;
77+ mach_write_to_4(buffer + offset * 4, bpage->offset);
78+ offset++;
79+
80+ if (offset == UNIV_PAGE_SIZE/4) {
81+ success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
82+ (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
83+ (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
84+ UNIV_PAGE_SIZE);
85+ if (!success) {
86+ mutex_exit(&buf_pool->LRU_list_mutex);
87+ fprintf(stderr,
88+ " InnoDB: cannot write page %lu of %s\n",
89+ buffers, LRU_DUMP_FILE);
90+ goto end;
91+ }
92+ buffers++;
93+ offset = 0;
94+ }
95+
96+ bpage = UT_LIST_GET_PREV(LRU, bpage);
97+ }
98+ mutex_exit(&buf_pool->LRU_list_mutex);
99+ }
100+
101+ if (offset == 0) {
102+ memset(buffer, 0, UNIV_PAGE_SIZE);
103+ }
104+
105+ mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
106+ offset++;
107+ mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
108+ offset++;
109+
110+ success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
111+ (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
112+ (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
113+ UNIV_PAGE_SIZE);
114+ if (!success) {
115+ goto end;
116+ }
117+
118+ ret = TRUE;
119+end:
120+ if (dump_file != -1)
121+ os_file_close(dump_file);
122+ if (buffer_base)
123+ ut_free(buffer_base);
124+
125+ return(ret);
126+}
127+
128+typedef struct {
129+ ib_uint32_t space_id;
130+ ib_uint32_t page_no;
131+} dump_record_t;
132+
133+static int dump_record_cmp(const void *a, const void *b)
134+{
135+ const dump_record_t *rec1 = (dump_record_t *) a;
136+ const dump_record_t *rec2 = (dump_record_t *) b;
137+
138+ if (rec1->space_id < rec2->space_id)
139+ return -1;
140+ if (rec1->space_id > rec2->space_id)
141+ return 1;
142+ if (rec1->page_no < rec2->page_no)
143+ return -1;
144+ return rec1->page_no > rec2->page_no;
145+}
146+
147+/********************************************************************//**
148+Read the pages based on the specific file.*/
149+UNIV_INTERN
150+ibool
151+buf_LRU_file_restore(void)
152+/*======================*/
153+{
154+ os_file_t dump_file = -1;
155+ ibool success;
156+ byte* buffer_base = NULL;
157+ byte* buffer = NULL;
158+ ulint buffers;
159+ ulint offset;
160+ ulint reads = 0;
161+ ulint req = 0;
162+ ibool terminated = FALSE;
163+ ibool ret = FALSE;
164+ dump_record_t* records = NULL;
165+ ulint size;
166+ ulint size_high;
167+ ulint length;
168+
169+ dump_file = os_file_create_simple_no_error_handling(innodb_file_temp_key,
170+ LRU_DUMP_FILE, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
171+ if (!success || !os_file_get_size(dump_file, &size, &size_high)) {
172+ os_file_get_last_error(TRUE);
173+ fprintf(stderr,
174+ " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
175+ goto end;
176+ }
734d6226
AM
177+
178+ ut_print_timestamp(stderr);
179+ fprintf(stderr, " InnoDB: Restoring buffer pool pages from %s\n",
180+ LRU_DUMP_FILE);
181+
b4e1fa2c
AM
182+ if (size == 0 || size_high > 0 || size % 8) {
183+ fprintf(stderr, " InnoDB: broken LRU dump file\n");
184+ goto end;
185+ }
186+ buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE);
187+ buffer = ut_align(buffer_base, UNIV_PAGE_SIZE);
188+ records = ut_malloc(size);
189+ if (!buffer || !records) {
190+ fprintf(stderr,
191+ " InnoDB: cannot allocate buffer.\n");
192+ goto end;
193+ }
194+
195+ buffers = 0;
196+ length = 0;
197+ while (!terminated) {
198+ success = os_file_read(dump_file, buffer,
199+ (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
200+ (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
201+ UNIV_PAGE_SIZE);
202+ if (!success) {
203+ fprintf(stderr,
d8778560
AM
204+ " InnoDB: either could not read page %lu of %s,"
205+ " or terminated unexpectedly.\n",
b4e1fa2c
AM
206+ buffers, LRU_DUMP_FILE);
207+ goto end;
208+ }
209+
210+ for (offset = 0; offset < UNIV_PAGE_SIZE/4; offset += 2) {
211+ ulint space_id;
212+ ulint page_no;
213+
214+ space_id = mach_read_from_4(buffer + offset * 4);
215+ page_no = mach_read_from_4(buffer + (offset + 1) * 4);
216+ if (space_id == 0xFFFFFFFFUL
217+ || page_no == 0xFFFFFFFFUL) {
218+ terminated = TRUE;
219+ break;
220+ }
221+
222+ records[length].space_id = space_id;
223+ records[length].page_no = page_no;
224+ length++;
225+ if (length * 8 >= size) {
226+ fprintf(stderr,
227+ " InnoDB: could not find the "
228+ "end-of-file marker after reading "
229+ "the expected %lu bytes from the "
230+ "LRU dump file.\n"
231+ " InnoDB: this could be caused by a "
232+ "broken or incomplete file.\n"
233+ " InnoDB: trying to process what has "
234+ "been read so far.\n",
235+ size);
236+ terminated= TRUE;
237+ break;
238+ }
239+ }
240+ buffers++;
241+ }
242+
243+ qsort(records, length, sizeof(dump_record_t), dump_record_cmp);
244+
245+ for (offset = 0; offset < length; offset++) {
246+ ulint space_id;
247+ ulint page_no;
248+ ulint zip_size;
249+ ulint err;
250+ ib_int64_t tablespace_version;
251+
252+ space_id = records[offset].space_id;
253+ page_no = records[offset].page_no;
254+
255+ if (offset % 16 == 15) {
256+ os_aio_simulated_wake_handler_threads();
257+ buf_flush_free_margins(FALSE);
258+ }
259+
260+ zip_size = fil_space_get_zip_size(space_id);
261+ if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
262+ continue;
263+ }
264+
d8778560 265+ if (fil_is_exist(space_id, page_no)) {
b4e1fa2c
AM
266+
267+ tablespace_version = fil_space_get_version(space_id);
268+
269+ req++;
270+ reads += buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
271+ | OS_AIO_SIMULATED_WAKE_LATER,
272+ space_id, zip_size, TRUE,
273+ tablespace_version, page_no, NULL);
274+ buf_LRU_stat_inc_io();
275+ }
276+ }
277+
278+ os_aio_simulated_wake_handler_threads();
279+ buf_flush_free_margins(FALSE);
280+
281+ ut_print_timestamp(stderr);
282+ fprintf(stderr,
734d6226 283+ " InnoDB: Completed reading buffer pool pages"
b4e1fa2c
AM
284+ " (requested: %lu, read: %lu)\n", req, reads);
285+ ret = TRUE;
286+end:
287+ if (dump_file != -1)
288+ os_file_close(dump_file);
289+ if (buffer_base)
290+ ut_free(buffer_base);
291+ if (records)
292+ ut_free(records);
293+
294+ return(ret);
295+}
296+
297 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
298 /**********************************************************************//**
299 Validates the LRU list for one buffer pool instance. */
db82db79
AM
300--- a/storage/innobase/buf/buf0rea.c
301+++ b/storage/innobase/buf/buf0rea.c
734d6226 302@@ -60,7 +60,7 @@
b4e1fa2c
AM
303 which case it is never read into the pool, or if the tablespace does
304 not exist or is being dropped
305 @return 1 if read request is issued. 0 if it is not */
306-static
307+UNIV_INTERN
308 ulint
309 buf_read_page_low(
310 /*==============*/
db82db79
AM
311--- a/storage/innobase/fil/fil0fil.c
312+++ b/storage/innobase/fil/fil0fil.c
29ffd636 313@@ -5307,6 +5307,70 @@
b4e1fa2c
AM
314 return(DB_SUCCESS);
315 }
316
317+/********************************************************************//**
318+Confirm whether the parameters are valid or not */
319+UNIV_INTERN
320+ibool
d8778560 321+fil_is_exist(
b4e1fa2c
AM
322+/*==============*/
323+ ulint space_id, /*!< in: space id */
d8778560 324+ ulint block_offset) /*!< in: offset in number of blocks */
b4e1fa2c
AM
325+{
326+ fil_space_t* space;
327+ fil_node_t* node;
328+
329+ /* Reserve the fil_system mutex and make sure that we can open at
330+ least one file while holding it, if the file is not already open */
331+
332+ fil_mutex_enter_and_prepare_for_io(space_id);
333+
334+ space = fil_space_get_by_id(space_id);
335+
336+ if (!space) {
337+ mutex_exit(&fil_system->mutex);
338+ return(FALSE);
339+ }
340+
341+ node = UT_LIST_GET_FIRST(space->chain);
342+
343+ for (;;) {
344+ if (UNIV_UNLIKELY(node == NULL)) {
345+ mutex_exit(&fil_system->mutex);
346+ return(FALSE);
347+ }
348+
349+ if (space->id != 0 && node->size == 0) {
350+ /* We do not know the size of a single-table tablespace
351+ before we open the file */
352+
353+ break;
354+ }
355+
356+ if (node->size > block_offset) {
357+ /* Found! */
358+ break;
359+ } else {
360+ block_offset -= node->size;
361+ node = UT_LIST_GET_NEXT(chain, node);
362+ }
363+ }
364+
365+ /* Open file if closed */
366+ fil_node_prepare_for_io(node, fil_system, space);
367+ fil_node_complete_io(node, fil_system, OS_FILE_READ);
368+
369+ /* Check that at least the start offset is within the bounds of a
370+ single-table tablespace */
371+ if (UNIV_UNLIKELY(node->size <= block_offset)
372+ && space->id != 0 && space->purpose == FIL_TABLESPACE) {
373+ mutex_exit(&fil_system->mutex);
374+ return(FALSE);
375+ }
376+
377+ mutex_exit(&fil_system->mutex);
378+ return(TRUE);
379+}
380+
381 #ifndef UNIV_HOTBACKUP
382 /**********************************************************************//**
383 Waits for an aio operation to complete. This function is used to write the
db82db79
AM
384--- a/storage/innobase/handler/ha_innodb.cc
385+++ b/storage/innobase/handler/ha_innodb.cc
734d6226
AM
386@@ -196,6 +196,8 @@
387
388 static char* innodb_version_str = (char*) INNODB_VERSION_STR;
389
390+static my_bool innobase_blocking_lru_restore = FALSE;
391+
392 /** Possible values for system variable "innodb_stats_method". The values
393 are defined the same as its corresponding MyISAM system variable
394 "myisam_stats_method"(see "myisam_stats_method_names"), for better usability */
395@@ -2652,6 +2654,8 @@
396 srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
397 srv_use_checksums = (ibool) innobase_use_checksums;
398
399+ srv_blocking_lru_restore = (ibool) innobase_blocking_lru_restore;
400+
401 #ifdef HAVE_LARGE_PAGES
402 if ((os_use_large_pages = (ibool) my_use_large_pages))
403 os_large_page_size = (ulint) opt_large_page_size;
29ffd636 404@@ -11964,6 +11968,19 @@
b4e1fa2c
AM
405 "Limit the allocated memory for dictionary cache. (0: unlimited)",
406 NULL, NULL, 0, 0, LONG_MAX, 0);
407
a9ee80b9 408+static MYSQL_SYSVAR_UINT(buffer_pool_restore_at_startup, srv_auto_lru_dump,
b4e1fa2c
AM
409+ PLUGIN_VAR_RQCMDARG,
410+ "Time in seconds between automatic buffer pool dumps. "
411+ "0 (the default) disables automatic dumps.",
412+ NULL, NULL, 0, 0, UINT_MAX32, 0);
734d6226
AM
413+
414+static MYSQL_SYSVAR_BOOL(blocking_buffer_pool_restore,
415+ innobase_blocking_lru_restore,
416+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
417+ "Block XtraDB startup process until buffer pool is full restored from a "
418+ "dump file (if present). Disabled by default.",
419+ NULL, NULL, FALSE);
b4e1fa2c
AM
420+
421 static struct st_mysql_sys_var* innobase_system_variables[]= {
422 MYSQL_SYSVAR(additional_mem_pool_size),
423 MYSQL_SYSVAR(autoextend_increment),
29ffd636 424@@ -12048,6 +12065,8 @@
734d6226 425 MYSQL_SYSVAR(random_read_ahead),
b4e1fa2c
AM
426 MYSQL_SYSVAR(read_ahead_threshold),
427 MYSQL_SYSVAR(io_capacity),
a9ee80b9 428+ MYSQL_SYSVAR(buffer_pool_restore_at_startup),
734d6226 429+ MYSQL_SYSVAR(blocking_buffer_pool_restore),
b4e1fa2c
AM
430 MYSQL_SYSVAR(purge_threads),
431 MYSQL_SYSVAR(purge_batch_size),
11822e22 432 MYSQL_SYSVAR(rollback_segments),
db82db79
AM
433--- a/storage/innobase/handler/i_s.cc
434+++ b/storage/innobase/handler/i_s.cc
b4e1fa2c
AM
435@@ -50,6 +50,7 @@
436 #include "trx0rseg.h" /* for trx_rseg_struct */
437 #include "trx0sys.h" /* for trx_sys */
438 #include "dict0dict.h" /* for dict_sys */
439+#include "buf0lru.h" /* for XTRA_LRU_[DUMP/RESTORE] */
440 }
441
adf0fb13 442 #define OK(expr) \
1bfc1981 443@@ -4336,6 +4337,36 @@
b4e1fa2c
AM
444 "Hello!");
445 goto end_func;
446 }
447+ else if (!strncasecmp("XTRA_LRU_DUMP", ptr, 13)) {
448+ ut_print_timestamp(stderr);
d8778560 449+ fprintf(stderr, " InnoDB: Administrative command 'XTRA_LRU_DUMP'"
b4e1fa2c
AM
450+ " was detected.\n");
451+
452+ if (buf_LRU_file_dump()) {
453+ field_store_string(i_s_table->field[0],
454+ "XTRA_LRU_DUMP was succeeded.");
455+ } else {
456+ field_store_string(i_s_table->field[0],
457+ "XTRA_LRU_DUMP was failed.");
458+ }
459+
460+ goto end_func;
461+ }
462+ else if (!strncasecmp("XTRA_LRU_RESTORE", ptr, 16)) {
463+ ut_print_timestamp(stderr);
d8778560 464+ fprintf(stderr, " InnoDB: Administrative command 'XTRA_LRU_RESTORE'"
b4e1fa2c
AM
465+ " was detected.\n");
466+
467+ if (buf_LRU_file_restore()) {
468+ field_store_string(i_s_table->field[0],
469+ "XTRA_LRU_RESTORE was succeeded.");
470+ } else {
471+ field_store_string(i_s_table->field[0],
472+ "XTRA_LRU_RESTORE was failed.");
473+ }
474+
475+ goto end_func;
476+ }
477
478 field_store_string(i_s_table->field[0],
479 "Undefined XTRA_* command.");
db82db79
AM
480--- a/storage/innobase/include/buf0lru.h
481+++ b/storage/innobase/include/buf0lru.h
482@@ -204,6 +204,18 @@
b4e1fa2c
AM
483 void
484 buf_LRU_stat_update(void);
485 /*=====================*/
486+/********************************************************************//**
487+Dump the LRU page list to the specific file. */
488+UNIV_INTERN
489+ibool
490+buf_LRU_file_dump(void);
491+/*===================*/
492+/********************************************************************//**
493+Read the pages based on the specific file.*/
494+UNIV_INTERN
495+ibool
496+buf_LRU_file_restore(void);
497+/*======================*/
498
734d6226
AM
499 /******************************************************************//**
500 Remove one page from LRU list and put it to free list */
db82db79
AM
501--- a/storage/innobase/include/buf0rea.h
502+++ b/storage/innobase/include/buf0rea.h
b4e1fa2c
AM
503@@ -31,6 +31,37 @@
504 #include "buf0types.h"
505
506 /********************************************************************//**
507+Low-level function which reads a page asynchronously from a file to the
508+buffer buf_pool if it is not already there, in which case does nothing.
509+Sets the io_fix flag and sets an exclusive lock on the buffer frame. The
510+flag is cleared and the x-lock released by an i/o-handler thread.
511+@return 1 if a read request was queued, 0 if the page already resided
512+in buf_pool, or if the page is in the doublewrite buffer blocks in
513+which case it is never read into the pool, or if the tablespace does
514+not exist or is being dropped
515+@return 1 if read request is issued. 0 if it is not */
516+UNIV_INTERN
517+ulint
518+buf_read_page_low(
519+/*==============*/
520+ ulint* err, /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are
521+ trying to read from a non-existent tablespace, or a
522+ tablespace which is just now being dropped */
523+ ibool sync, /*!< in: TRUE if synchronous aio is desired */
524+ ulint mode, /*!< in: BUF_READ_IBUF_PAGES_ONLY, ...,
525+ ORed to OS_AIO_SIMULATED_WAKE_LATER (see below
526+ at read-ahead functions) */
527+ ulint space, /*!< in: space id */
528+ ulint zip_size,/*!< in: compressed page size, or 0 */
529+ ibool unzip, /*!< in: TRUE=request uncompressed page */
530+ ib_int64_t tablespace_version, /*!< in: if the space memory object has
531+ this timestamp different from what we are giving here,
532+ treat the tablespace as dropped; this is a timestamp we
533+ use to stop dangling page reads from a tablespace
534+ which we have DISCARDed + IMPORTed back */
535+ ulint offset, /*!< in: page number */
536+ trx_t* trx);
537+/********************************************************************//**
538 High-level function which reads a page asynchronously from a file to the
539 buffer buf_pool if it is not already there. Sets the io_fix flag and sets
540 an exclusive lock on the buffer frame. The flag is cleared and the x-lock
db82db79
AM
541--- a/storage/innobase/include/fil0fil.h
542+++ b/storage/innobase/include/fil0fil.h
29ffd636 543@@ -653,6 +653,14 @@
b4e1fa2c
AM
544 void* message, /*!< in: message for aio handler if non-sync
545 aio used, else ignored */
546 trx_t* trx);
547+/********************************************************************//**
548+Confirm whether the parameters are valid or not */
549+UNIV_INTERN
550+ibool
d8778560 551+fil_is_exist(
b4e1fa2c
AM
552+/*==============*/
553+ ulint space_id, /*!< in: space id */
d8778560 554+ ulint block_offset); /*!< in: offset in number of blocks */
b4e1fa2c
AM
555 /**********************************************************************//**
556 Waits for an aio operation to complete. This function is used to write the
557 handler for completed requests. The aio array of pending requests is divided
db82db79
AM
558--- a/storage/innobase/include/srv0srv.h
559+++ b/storage/innobase/include/srv0srv.h
29ffd636 560@@ -364,6 +364,12 @@
b4e1fa2c
AM
561 reading of a disk page */
562 extern ulint srv_buf_pool_reads;
563
564+/** Time in seconds between automatic buffer pool dumps */
565+extern uint srv_auto_lru_dump;
734d6226
AM
566+
567+/** Whether startup should be blocked until buffer pool is fully restored */
568+extern ibool srv_blocking_lru_restore;
b4e1fa2c
AM
569+
570 /** Status variables to be passed to MySQL */
571 typedef struct export_var_struct export_struc;
572
29ffd636 573@@ -669,6 +675,16 @@
b4e1fa2c
AM
574 /*=====================*/
575 void* arg); /*!< in: a dummy parameter required by
576 os_thread_create */
577+/*********************************************************************//**
578+A thread which restores the buffer pool from a dump file on startup and does
579+periodic buffer pool dumps.
580+@return a dummy parameter */
581+UNIV_INTERN
582+os_thread_ret_t
583+srv_LRU_dump_restore_thread(
584+/*====================*/
585+ void* arg); /*!< in: a dummy parameter required by
586+ os_thread_create */
587 /******************************************************************//**
588 Outputs to a file the output of the InnoDB Monitor.
589 @return FALSE if not all information printed
db82db79
AM
590--- a/storage/innobase/srv/srv0srv.c
591+++ b/storage/innobase/srv/srv0srv.c
734d6226 592@@ -332,6 +332,12 @@
b4e1fa2c
AM
593 reading of a disk page */
594 UNIV_INTERN ulint srv_buf_pool_reads = 0;
595
596+/** Time in seconds between automatic buffer pool dumps */
597+UNIV_INTERN uint srv_auto_lru_dump = 0;
734d6226
AM
598+
599+/** Whether startup should be blocked until buffer pool is fully restored */
600+UNIV_INTERN ibool srv_blocking_lru_restore;
b4e1fa2c
AM
601+
602 /* structure to pass status variables to MySQL */
603 UNIV_INTERN export_struc export_vars;
604
29ffd636
AM
605@@ -2708,6 +2714,58 @@
606 /* We count the number of threads in os_thread_exit(). A created
607 thread should always use that to exit and not use return() to exit. */
b4e1fa2c 608
29ffd636
AM
609+ os_thread_exit(NULL);
610+
611+ OS_THREAD_DUMMY_RETURN;
612+}
613+
b4e1fa2c
AM
614+/*********************************************************************//**
615+A thread which restores the buffer pool from a dump file on startup and does
616+periodic buffer pool dumps.
617+@return a dummy parameter */
618+UNIV_INTERN
619+os_thread_ret_t
620+srv_LRU_dump_restore_thread(
621+/*====================*/
622+ void* arg __attribute__((unused)))
623+ /*!< in: a dummy parameter required by
624+ os_thread_create */
625+{
626+ uint auto_lru_dump;
627+ time_t last_dump_time;
628+ time_t time_elapsed;
629+
630+#ifdef UNIV_DEBUG_THREAD_CREATION
d8778560 631+ fprintf(stderr, "The LRU dump/restore thread has started, id %lu\n",
b4e1fa2c
AM
632+ os_thread_pf(os_thread_get_curr_id()));
633+#endif
634+
734d6226
AM
635+ /* If srv_blocking_lru_restore is TRUE, restore will be done
636+ synchronously on startup. */
637+ if (srv_auto_lru_dump && !srv_blocking_lru_restore)
b4e1fa2c
AM
638+ buf_LRU_file_restore();
639+
640+ last_dump_time = time(NULL);
641+
642+loop:
643+ os_thread_sleep(5000000);
644+
645+ if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
646+ goto exit_func;
647+ }
648+
649+ time_elapsed = time(NULL) - last_dump_time;
650+ auto_lru_dump = srv_auto_lru_dump;
651+ if (auto_lru_dump > 0 && (time_t) auto_lru_dump < time_elapsed) {
652+ last_dump_time = time(NULL);
653+ buf_LRU_file_dump();
654+ }
655+
656+ goto loop;
657+exit_func:
658+ /* We count the number of threads in os_thread_exit(). A created
659+ thread should always use that to exit and not use return() to exit. */
660+
29ffd636
AM
661 os_thread_exit(NULL);
662
663 OS_THREAD_DUMMY_RETURN;
db82db79
AM
664--- a/storage/innobase/srv/srv0start.c
665+++ b/storage/innobase/srv/srv0start.c
734d6226
AM
666@@ -87,6 +87,7 @@
667 # include "btr0pcur.h"
668 # include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
669 # include "zlib.h" /* for ZLIB_VERSION */
670+# include "buf0lru.h" /* for buf_LRU_file_restore() */
671
672 /** Log sequence number immediately after startup */
673 UNIV_INTERN ib_uint64_t srv_start_lsn;
674@@ -120,9 +121,9 @@
b4e1fa2c
AM
675 static os_file_t files[1000];
676
677 /** io_handler_thread parameters for thread identification */
678-static ulint n[SRV_MAX_N_IO_THREADS + 6];
679+static ulint n[SRV_MAX_N_IO_THREADS + 7];
680 /** io_handler_thread identifiers */
681-static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6];
682+static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 7];
683
684 /** We use this mutex to test the return value of pthread_mutex_trylock
685 on successful locking. HP-UX does NOT return 0, though Linux et al do. */
29ffd636 686@@ -1841,6 +1842,15 @@
b4e1fa2c
AM
687 os_thread_create(&srv_monitor_thread, NULL,
688 thread_ids + 4 + SRV_MAX_N_IO_THREADS);
689
690+ /* Create the thread which automaticaly dumps/restore buffer pool */
691+ os_thread_create(&srv_LRU_dump_restore_thread, NULL,
692+ thread_ids + 5 + SRV_MAX_N_IO_THREADS);
734d6226
AM
693+
694+ /* If srv_blocking_lru_restore is TRUE, load buffer pool contents
695+ synchronously */
696+ if (srv_auto_lru_dump && srv_blocking_lru_restore)
697+ buf_LRU_file_restore();
b4e1fa2c
AM
698+
699 srv_is_being_started = FALSE;
700
701 err = dict_create_or_check_foreign_constraint_tables();
734d6226
AM
702--- /dev/null
703+++ b/mysql-test/suite/sys_vars/r/innodb_blocking_buffer_pool_restore_basic.result
704@@ -0,0 +1,3 @@
705+SELECT @@global.innodb_blocking_buffer_pool_restore;
706+@@global.innodb_blocking_buffer_pool_restore
707+0
708--- /dev/null
709+++ b/mysql-test/suite/sys_vars/t/innodb_blocking_buffer_pool_restore_basic.test
710@@ -0,0 +1 @@
711+SELECT @@global.innodb_blocking_buffer_pool_restore;
This page took 0.135484 seconds and 4 git commands to generate.