~percona-dev/percona-server/release-5.1.52-12-build

« back to all changes in this revision

Viewing changes to innodb_lru_dump_restore.patch

  • Committer: kinoyasu
  • Date: 2010-04-30 10:17:55 UTC
  • Revision ID: kinoyasu@gauntlet3-20100430101755-h27x25t4uax76lv4
merge, reorder and port patches based on mysql 5.1.46 innodb 1.0.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
diff -ruN a/storage/innodb_plugin/buf/buf0lru.c b/storage/innodb_plugin/buf/buf0lru.c
 
2
--- a/storage/innodb_plugin/buf/buf0lru.c       2010-04-29 18:58:20.000000000 +0900
 
3
+++ b/storage/innodb_plugin/buf/buf0lru.c       2010-04-30 15:47:10.000000000 +0900
 
4
@@ -2107,6 +2107,218 @@
 
5
        memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur);
 
6
 }
 
7
 
 
8
+/********************************************************************//**
 
9
+Dump the LRU page list to the specific file. */
 
10
+#define LRU_DUMP_FILE "ib_lru_dump"
 
11
+
 
12
+UNIV_INTERN
 
13
+ibool
 
14
+buf_LRU_file_dump(void)
 
15
+/*===================*/
 
16
+{
 
17
+       os_file_t       dump_file = -1;
 
18
+       ibool           success;
 
19
+       byte*           buffer_base = NULL;
 
20
+       byte*           buffer = NULL;
 
21
+       buf_page_t*     bpage;
 
22
+       ulint           buffers;
 
23
+       ulint           offset;
 
24
+       ibool           ret = FALSE;
 
25
+       ulint           i;
 
26
+
 
27
+       for (i = 0; i < srv_n_data_files; i++) {
 
28
+               if (strstr(srv_data_file_names[i], LRU_DUMP_FILE) != NULL) {
 
29
+                       fprintf(stderr,
 
30
+                               " InnoDB: The name '%s' seems to be used for"
 
31
+                               " innodb_data_file_path. Dumping LRU list is not"
 
32
+                               " done for safeness.\n", LRU_DUMP_FILE);
 
33
+                       goto end;
 
34
+               }
 
35
+       }
 
36
+
 
37
+       buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE);
 
38
+       buffer = ut_align(buffer_base, UNIV_PAGE_SIZE);
 
39
+       if (!buffer) {
 
40
+               fprintf(stderr,
 
41
+                       " InnoDB: cannot allocate buffer.\n");
 
42
+               goto end;
 
43
+       }
 
44
+
 
45
+       dump_file = os_file_create(LRU_DUMP_FILE, OS_FILE_OVERWRITE,
 
46
+                               OS_FILE_NORMAL, OS_DATA_FILE, &success);
 
47
+       if (!success) {
 
48
+               os_file_get_last_error(TRUE);
 
49
+               fprintf(stderr,
 
50
+                       " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
 
51
+               goto end;
 
52
+       }
 
53
+
 
54
+       mutex_enter(&LRU_list_mutex);
 
55
+       bpage = UT_LIST_GET_LAST(buf_pool->LRU);
 
56
+
 
57
+       buffers = offset = 0;
 
58
+       while (bpage != NULL) {
 
59
+               if (offset == 0) {
 
60
+                       memset(buffer, 0, UNIV_PAGE_SIZE);
 
61
+               }
 
62
+
 
63
+               mach_write_to_4(buffer + offset * 4, bpage->space);
 
64
+               offset++;
 
65
+               mach_write_to_4(buffer + offset * 4, bpage->offset);
 
66
+               offset++;
 
67
+
 
68
+               if (offset == UNIV_PAGE_SIZE/4) {
 
69
+                       success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
 
70
+                                       (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
 
71
+                                       (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
 
72
+                                       UNIV_PAGE_SIZE);
 
73
+                       if (!success) {
 
74
+                               mutex_exit(&LRU_list_mutex);
 
75
+                               fprintf(stderr,
 
76
+                                       " InnoDB: cannot write page %lu of %s\n",
 
77
+                                       buffers, LRU_DUMP_FILE);
 
78
+                               goto end;
 
79
+                       }
 
80
+                       buffers++;
 
81
+                       offset = 0;
 
82
+               }
 
83
+
 
84
+               bpage = UT_LIST_GET_PREV(LRU, bpage);
 
85
+       }
 
86
+       mutex_exit(&LRU_list_mutex);
 
87
+
 
88
+       if (offset == 0) {
 
89
+               memset(buffer, 0, UNIV_PAGE_SIZE);
 
90
+       }
 
91
+
 
92
+       mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
 
93
+       offset++;
 
94
+       mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
 
95
+       offset++;
 
96
+
 
97
+       success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
 
98
+                       (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
 
99
+                       (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
 
100
+                       UNIV_PAGE_SIZE);
 
101
+       if (!success) {
 
102
+               goto end;
 
103
+       }
 
104
+
 
105
+       ret = TRUE;
 
106
+end:
 
107
+       if (dump_file != -1)
 
108
+               os_file_close(dump_file);
 
109
+       if (buffer_base)
 
110
+               ut_free(buffer_base);
 
111
+
 
112
+       return(ret);
 
113
+}
 
114
+/********************************************************************//**
 
115
+Read the pages based on the specific file.*/
 
116
+UNIV_INTERN
 
117
+ibool
 
118
+buf_LRU_file_restore(void)
 
119
+/*======================*/
 
120
+{
 
121
+       os_file_t       dump_file = -1;
 
122
+       ibool           success;
 
123
+       byte*           buffer_base = NULL;
 
124
+       byte*           buffer = NULL;
 
125
+       ulint           buffers;
 
126
+       ulint           offset;
 
127
+       ulint           reads = 0;
 
128
+       ulint           req = 0;
 
129
+       ibool           terminated = FALSE;
 
130
+       ibool           ret = FALSE;
 
131
+
 
132
+       buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE);
 
133
+       buffer = ut_align(buffer_base, UNIV_PAGE_SIZE);
 
134
+       if (!buffer) {
 
135
+               fprintf(stderr,
 
136
+                       " InnoDB: cannot allocate buffer.\n");
 
137
+               goto end;
 
138
+       }
 
139
+
 
140
+       dump_file = os_file_create_simple_no_error_handling(
 
141
+               LRU_DUMP_FILE, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
 
142
+       if (!success) {
 
143
+               os_file_get_last_error(TRUE);
 
144
+               fprintf(stderr,
 
145
+                       " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
 
146
+               goto end;
 
147
+       }
 
148
+
 
149
+       buffers = 0;
 
150
+       while (!terminated) {
 
151
+               success = os_file_read(dump_file, buffer,
 
152
+                               (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
 
153
+                               (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
 
154
+                               UNIV_PAGE_SIZE);
 
155
+               if (!success) {
 
156
+                       fprintf(stderr,
 
157
+                               " InnoDB: cannot read page %lu of %s,"
 
158
+                               " or meet unexpected terminal.",
 
159
+                               buffers, LRU_DUMP_FILE);
 
160
+                       goto end;
 
161
+               }
 
162
+
 
163
+               for (offset = 0; offset < UNIV_PAGE_SIZE/4; offset += 2) {
 
164
+                       ulint   space_id, zip_size, page_no;
 
165
+                       ulint   err;
 
166
+                       ib_int64_t      tablespace_version;
 
167
+
 
168
+                       space_id = mach_read_from_4(buffer + offset * 4);
 
169
+                       page_no = mach_read_from_4(buffer + (offset + 1) * 4);
 
170
+                       if (space_id == 0xFFFFFFFFUL
 
171
+                           || page_no == 0xFFFFFFFFUL) {
 
172
+                               terminated = TRUE;
 
173
+                               break;
 
174
+                       }
 
175
+
 
176
+                       if (offset % 16 == 15) {
 
177
+                               os_aio_simulated_wake_handler_threads();
 
178
+                               buf_flush_free_margin(FALSE);
 
179
+                       }
 
180
+
 
181
+                       zip_size = fil_space_get_zip_size(space_id);
 
182
+                       if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
 
183
+                               continue;
 
184
+                       }
 
185
+
 
186
+                       if (fil_area_is_exist(space_id, zip_size, page_no, 0,
 
187
+                                       zip_size ? zip_size : UNIV_PAGE_SIZE)) {
 
188
+
 
189
+                               tablespace_version = fil_space_get_version(space_id);
 
190
+
 
191
+                               req++;
 
192
+                               reads += buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
 
193
+                                                 | OS_AIO_SIMULATED_WAKE_LATER,
 
194
+                                                 space_id, zip_size, TRUE,
 
195
+                                                 tablespace_version, page_no, NULL);
 
196
+                               buf_LRU_stat_inc_io();
 
197
+                       }
 
198
+               }
 
199
+
 
200
+               buffers++;
 
201
+       }
 
202
+
 
203
+       os_aio_simulated_wake_handler_threads();
 
204
+       buf_flush_free_margin(FALSE);
 
205
+
 
206
+       ut_print_timestamp(stderr);
 
207
+       fprintf(stderr,
 
208
+               " InnoDB: reading pages based on the dumped LRU list was done."
 
209
+               " (requested: %lu, read: %lu)\n", req, reads);
 
210
+       ret = TRUE;
 
211
+end:
 
212
+       if (dump_file != -1)
 
213
+               os_file_close(dump_file);
 
214
+       if (buffer_base)
 
215
+               ut_free(buffer_base);
 
216
+
 
217
+       return(ret);
 
218
+}
 
219
+
 
220
 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 
221
 /**********************************************************************//**
 
222
 Validates the LRU list.
 
223
diff -ruN a/storage/innodb_plugin/buf/buf0rea.c b/storage/innodb_plugin/buf/buf0rea.c
 
224
--- a/storage/innodb_plugin/buf/buf0rea.c       2010-04-30 15:01:51.000000000 +0900
 
225
+++ b/storage/innodb_plugin/buf/buf0rea.c       2010-04-30 15:47:10.000000000 +0900
 
226
@@ -56,7 +56,7 @@
 
227
 which case it is never read into the pool, or if the tablespace does
 
228
 not exist or is being dropped 
 
229
 @return 1 if read request is issued. 0 if it is not */
 
230
-static
 
231
+UNIV_INTERN
 
232
 ulint
 
233
 buf_read_page_low(
 
234
 /*==============*/
 
235
diff -ruN a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
 
236
--- a/storage/innodb_plugin/fil/fil0fil.c       2010-04-30 15:01:51.000000000 +0900
 
237
+++ b/storage/innodb_plugin/fil/fil0fil.c       2010-04-30 15:47:10.000000000 +0900
 
238
@@ -4765,6 +4765,78 @@
 
239
        return(DB_SUCCESS);
 
240
 }
 
241
 
 
242
+/********************************************************************//**
 
243
+Confirm whether the parameters are valid or not */
 
244
+UNIV_INTERN
 
245
+ibool
 
246
+fil_area_is_exist(
 
247
+/*==============*/
 
248
+       ulint   space_id,       /*!< in: space id */
 
249
+       ulint   zip_size,       /*!< in: compressed page size in bytes;
 
250
+                               0 for uncompressed pages */
 
251
+       ulint   block_offset,   /*!< in: offset in number of blocks */
 
252
+       ulint   byte_offset,    /*!< in: remainder of offset in bytes; in
 
253
+                               aio this must be divisible by the OS block
 
254
+                               size */
 
255
+       ulint   len)            /*!< in: how many bytes to read or write; this
 
256
+                               must not cross a file boundary; in aio this
 
257
+                               must be a block size multiple */
 
258
+{
 
259
+       fil_space_t*    space;
 
260
+       fil_node_t*     node;
 
261
+
 
262
+       /* Reserve the fil_system mutex and make sure that we can open at
 
263
+       least one file while holding it, if the file is not already open */
 
264
+
 
265
+       fil_mutex_enter_and_prepare_for_io(space_id);
 
266
+
 
267
+       space = fil_space_get_by_id(space_id);
 
268
+
 
269
+       if (!space) {
 
270
+               mutex_exit(&fil_system->mutex);
 
271
+               return(FALSE);
 
272
+       }
 
273
+
 
274
+       node = UT_LIST_GET_FIRST(space->chain);
 
275
+
 
276
+       for (;;) {
 
277
+               if (UNIV_UNLIKELY(node == NULL)) {
 
278
+                       mutex_exit(&fil_system->mutex);
 
279
+                       return(FALSE);
 
280
+               }
 
281
+
 
282
+               if (space->id != 0 && node->size == 0) {
 
283
+                       /* We do not know the size of a single-table tablespace
 
284
+                       before we open the file */
 
285
+
 
286
+                       break;
 
287
+               }
 
288
+
 
289
+               if (node->size > block_offset) {
 
290
+                       /* Found! */
 
291
+                       break;
 
292
+               } else {
 
293
+                       block_offset -= node->size;
 
294
+                       node = UT_LIST_GET_NEXT(chain, node);
 
295
+               }
 
296
+       }
 
297
+
 
298
+       /* Open file if closed */
 
299
+       fil_node_prepare_for_io(node, fil_system, space);
 
300
+       fil_node_complete_io(node, fil_system, OS_FILE_READ);
 
301
+
 
302
+       /* Check that at least the start offset is within the bounds of a
 
303
+       single-table tablespace */
 
304
+       if (UNIV_UNLIKELY(node->size <= block_offset)
 
305
+           && space->id != 0 && space->purpose == FIL_TABLESPACE) {
 
306
+               mutex_exit(&fil_system->mutex);
 
307
+               return(FALSE);
 
308
+       }
 
309
+
 
310
+       mutex_exit(&fil_system->mutex);
 
311
+       return(TRUE);
 
312
+}
 
313
+
 
314
 #ifndef UNIV_HOTBACKUP
 
315
 /**********************************************************************//**
 
316
 Waits for an aio operation to complete. This function is used to write the
 
317
diff -ruN a/storage/innodb_plugin/handler/i_s.cc b/storage/innodb_plugin/handler/i_s.cc
 
318
--- a/storage/innodb_plugin/handler/i_s.cc      2010-04-30 14:38:27.000000000 +0900
 
319
+++ b/storage/innodb_plugin/handler/i_s.cc      2010-04-30 15:47:10.000000000 +0900
 
320
@@ -47,6 +47,7 @@
 
321
 #include "trx0rseg.h" /* for trx_rseg_struct */
 
322
 #include "trx0sys.h" /* for trx_sys */
 
323
 #include "dict0dict.h" /* for dict_sys */
 
324
+#include "buf0lru.h" /* for XTRA_LRU_[DUMP/RESTORE] */
 
325
 /* from buf0buf.c */
 
326
 struct buf_chunk_struct{
 
327
        ulint           mem_size;       /* allocated size of the chunk */
 
328
@@ -3091,6 +3092,36 @@
 
329
                        "Hello!");
 
330
                goto end_func;
 
331
        }
 
332
+       else if (!strncasecmp("XTRA_LRU_DUMP", ptr, 13)) {
 
333
+               ut_print_timestamp(stderr);
 
334
+               fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_DUMP'"
 
335
+                               " was detected.\n");
 
336
+
 
337
+               if (buf_LRU_file_dump()) {
 
338
+                       field_store_string(i_s_table->field[0],
 
339
+                               "XTRA_LRU_DUMP was succeeded.");
 
340
+               } else {
 
341
+                       field_store_string(i_s_table->field[0],
 
342
+                               "XTRA_LRU_DUMP was failed.");
 
343
+               }
 
344
+
 
345
+               goto end_func;
 
346
+       }
 
347
+       else if (!strncasecmp("XTRA_LRU_RESTORE", ptr, 16)) {
 
348
+               ut_print_timestamp(stderr);
 
349
+               fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_RESTORE'"
 
350
+                               " was detected.\n");
 
351
+
 
352
+               if (buf_LRU_file_restore()) {
 
353
+                       field_store_string(i_s_table->field[0],
 
354
+                               "XTRA_LRU_RESTORE was succeeded.");
 
355
+               } else {
 
356
+                       field_store_string(i_s_table->field[0],
 
357
+                               "XTRA_LRU_RESTORE was failed.");
 
358
+               }
 
359
+
 
360
+               goto end_func;
 
361
+       }
 
362
 
 
363
        field_store_string(i_s_table->field[0],
 
364
                "Undefined XTRA_* command.");
 
365
diff -ruN a/storage/innodb_plugin/handler/innodb_patch_info.h b/storage/innodb_plugin/handler/innodb_patch_info.h
 
366
--- a/storage/innodb_plugin/handler/innodb_patch_info.h 2010-04-30 15:46:35.000000000 +0900
 
367
+++ b/storage/innodb_plugin/handler/innodb_patch_info.h 2010-04-30 15:47:10.000000000 +0900
 
368
@@ -42,5 +42,6 @@
 
369
 {"innodb_show_lock_name","Show mutex/lock name instead of crated file/line","","http://www.percona.com/docs/wiki/percona-xtradb"},
 
370
 {"innodb_extend_slow","Extended statistics in slow.log","It is InnoDB-part only. It needs to patch also to mysqld.","http://www.percona.com/docs/wiki/percona-xtradb"},
 
371
 {"innodb_relax_table_creation","Relax limitation of column size at table creation as builtin InnoDB.","","http://www.percona.com/docs/wiki/percona-xtradb"},
 
372
+{"innodb_lru_dump_restore","Dump and restore command for content of buffer pool","","http://www.percona.com/docs/wiki/percona-xtradb"},
 
373
 {NULL, NULL, NULL, NULL}
 
374
 };
 
375
diff -ruN a/storage/innodb_plugin/include/buf0lru.h b/storage/innodb_plugin/include/buf0lru.h
 
376
--- a/storage/innodb_plugin/include/buf0lru.h   2010-04-29 18:58:20.000000000 +0900
 
377
+++ b/storage/innodb_plugin/include/buf0lru.h   2010-04-30 15:47:10.000000000 +0900
 
378
@@ -213,6 +213,18 @@
 
379
 void
 
380
 buf_LRU_stat_update(void);
 
381
 /*=====================*/
 
382
+/********************************************************************//**
 
383
+Dump the LRU page list to the specific file. */
 
384
+UNIV_INTERN
 
385
+ibool
 
386
+buf_LRU_file_dump(void);
 
387
+/*===================*/
 
388
+/********************************************************************//**
 
389
+Read the pages based on the specific file.*/
 
390
+UNIV_INTERN
 
391
+ibool
 
392
+buf_LRU_file_restore(void);
 
393
+/*======================*/
 
394
 
 
395
 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 
396
 /**********************************************************************//**
 
397
diff -ruN a/storage/innodb_plugin/include/buf0rea.h b/storage/innodb_plugin/include/buf0rea.h
 
398
--- a/storage/innodb_plugin/include/buf0rea.h   2010-04-30 15:01:51.000000000 +0900
 
399
+++ b/storage/innodb_plugin/include/buf0rea.h   2010-04-30 15:47:10.000000000 +0900
 
400
@@ -31,6 +31,37 @@
 
401
 #include "buf0types.h"
 
402
 
 
403
 /********************************************************************//**
 
404
+Low-level function which reads a page asynchronously from a file to the
 
405
+buffer buf_pool if it is not already there, in which case does nothing.
 
406
+Sets the io_fix flag and sets an exclusive lock on the buffer frame. The
 
407
+flag is cleared and the x-lock released by an i/o-handler thread.
 
408
+@return 1 if a read request was queued, 0 if the page already resided
 
409
+in buf_pool, or if the page is in the doublewrite buffer blocks in
 
410
+which case it is never read into the pool, or if the tablespace does
 
411
+not exist or is being dropped 
 
412
+@return 1 if read request is issued. 0 if it is not */
 
413
+UNIV_INTERN
 
414
+ulint
 
415
+buf_read_page_low(
 
416
+/*==============*/
 
417
+       ulint*  err,    /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are
 
418
+                       trying to read from a non-existent tablespace, or a
 
419
+                       tablespace which is just now being dropped */
 
420
+       ibool   sync,   /*!< in: TRUE if synchronous aio is desired */
 
421
+       ulint   mode,   /*!< in: BUF_READ_IBUF_PAGES_ONLY, ...,
 
422
+                       ORed to OS_AIO_SIMULATED_WAKE_LATER (see below
 
423
+                       at read-ahead functions) */
 
424
+       ulint   space,  /*!< in: space id */
 
425
+       ulint   zip_size,/*!< in: compressed page size, or 0 */
 
426
+       ibool   unzip,  /*!< in: TRUE=request uncompressed page */
 
427
+       ib_int64_t tablespace_version, /*!< in: if the space memory object has
 
428
+                       this timestamp different from what we are giving here,
 
429
+                       treat the tablespace as dropped; this is a timestamp we
 
430
+                       use to stop dangling page reads from a tablespace
 
431
+                       which we have DISCARDed + IMPORTed back */
 
432
+       ulint   offset, /*!< in: page number */
 
433
+       trx_t*  trx);
 
434
+/********************************************************************//**
 
435
 High-level function which reads a page asynchronously from a file to the
 
436
 buffer buf_pool if it is not already there. Sets the io_fix flag and sets
 
437
 an exclusive lock on the buffer frame. The flag is cleared and the x-lock
 
438
diff -ruN a/storage/innodb_plugin/include/fil0fil.h b/storage/innodb_plugin/include/fil0fil.h
 
439
--- a/storage/innodb_plugin/include/fil0fil.h   2010-04-30 15:01:51.000000000 +0900
 
440
+++ b/storage/innodb_plugin/include/fil0fil.h   2010-04-30 15:47:10.000000000 +0900
 
441
@@ -645,6 +645,22 @@
 
442
        void*   message,        /*!< in: message for aio handler if non-sync
 
443
                                aio used, else ignored */
 
444
        trx_t*  trx);
 
445
+/********************************************************************//**
 
446
+Confirm whether the parameters are valid or not */
 
447
+UNIV_INTERN
 
448
+ibool
 
449
+fil_area_is_exist(
 
450
+/*==============*/
 
451
+       ulint   space_id,       /*!< in: space id */
 
452
+       ulint   zip_size,       /*!< in: compressed page size in bytes;
 
453
+                               0 for uncompressed pages */
 
454
+       ulint   block_offset,   /*!< in: offset in number of blocks */
 
455
+       ulint   byte_offset,    /*!< in: remainder of offset in bytes; in
 
456
+                               aio this must be divisible by the OS block
 
457
+                               size */
 
458
+       ulint   len);           /*!< in: how many bytes to read or write; this
 
459
+                               must not cross a file boundary; in aio this
 
460
+                               must be a block size multiple */
 
461
 /**********************************************************************//**
 
462
 Waits for an aio operation to complete. This function is used to write the
 
463
 handler for completed requests. The aio array of pending requests is divided