1 # name : innodb_recovery_patches.patch
2 # introduced : 11 or before
3 # maintainer : Yasufumi
6 # Any small change to this file in the main branch
7 # should be done or reviewed by the maintainer!
8 --- a/storage/innobase/buf/buf0rea.c
9 +++ b/storage/innobase/buf/buf0rea.c
11 bpage = buf_page_init_for_read(err, mode, space, zip_size, unzip,
12 tablespace_version, offset);
14 + /* bugfix: http://bugs.mysql.com/bug.php?id=43948 */
15 + if (recv_recovery_is_on() && *err == DB_TABLESPACE_DELETED) {
16 + /* hashed log recs must be treated here */
17 + recv_addr_t* recv_addr;
19 + mutex_enter(&(recv_sys->mutex));
21 + if (recv_sys->apply_log_recs == FALSE) {
22 + mutex_exit(&(recv_sys->mutex));
23 + goto not_to_recover;
26 + /* recv_get_fil_addr_struct() */
27 + recv_addr = HASH_GET_FIRST(recv_sys->addr_hash,
28 + hash_calc_hash(ut_fold_ulint_pair(space, offset),
29 + recv_sys->addr_hash));
31 + if ((recv_addr->space == space)
32 + && (recv_addr->page_no == offset)) {
35 + recv_addr = HASH_GET_NEXT(addr_hash, recv_addr);
38 + if ((recv_addr == NULL)
39 + || (recv_addr->state == RECV_BEING_PROCESSED)
40 + || (recv_addr->state == RECV_PROCESSED)) {
41 + mutex_exit(&(recv_sys->mutex));
42 + goto not_to_recover;
45 + fprintf(stderr, " (cannot find space: %lu)", space);
46 + recv_addr->state = RECV_PROCESSED;
48 + ut_a(recv_sys->n_addrs);
49 + recv_sys->n_addrs--;
51 + mutex_exit(&(recv_sys->mutex));
58 /* It is a single table tablespace and the .ibd file is
59 missing: do nothing */
61 + /* the log records should be treated here same reason
62 + for http://bugs.mysql.com/bug.php?id=43948 */
64 + if (recv_recovery_is_on()) {
65 + recv_addr_t* recv_addr;
67 + mutex_enter(&(recv_sys->mutex));
69 + if (recv_sys->apply_log_recs == FALSE) {
70 + mutex_exit(&(recv_sys->mutex));
71 + goto not_to_recover;
74 + for (i = 0; i < n_stored; i++) {
75 + /* recv_get_fil_addr_struct() */
76 + recv_addr = HASH_GET_FIRST(recv_sys->addr_hash,
77 + hash_calc_hash(ut_fold_ulint_pair(space, page_nos[i]),
78 + recv_sys->addr_hash));
80 + if ((recv_addr->space == space)
81 + && (recv_addr->page_no == page_nos[i])) {
84 + recv_addr = HASH_GET_NEXT(addr_hash, recv_addr);
87 + if ((recv_addr == NULL)
88 + || (recv_addr->state == RECV_BEING_PROCESSED)
89 + || (recv_addr->state == RECV_PROCESSED)) {
93 + recv_addr->state = RECV_PROCESSED;
95 + ut_a(recv_sys->n_addrs);
96 + recv_sys->n_addrs--;
99 + mutex_exit(&(recv_sys->mutex));
101 + fprintf(stderr, " (cannot find space: %lu)", space);
108 --- a/storage/innobase/handler/ha_innodb.cc
109 +++ b/storage/innobase/handler/ha_innodb.cc
111 #endif /* UNIV_LOG_ARCHIVE */
112 static my_bool innobase_use_doublewrite = TRUE;
113 static my_bool innobase_use_checksums = TRUE;
114 +static my_bool innobase_recovery_stats = TRUE;
115 static my_bool innobase_locks_unsafe_for_binlog = FALSE;
116 static my_bool innobase_overwrite_relay_log_info = FALSE;
117 static my_bool innobase_rollback_on_timeout = FALSE;
118 @@ -2610,6 +2611,8 @@
120 srv_force_recovery = (ulint) innobase_force_recovery;
122 + srv_recovery_stats = (ibool) innobase_recovery_stats;
124 srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
125 srv_use_checksums = (ibool) innobase_use_checksums;
127 @@ -11382,6 +11385,11 @@
128 "The common part for InnoDB table spaces.",
131 +static MYSQL_SYSVAR_BOOL(recovery_stats, innobase_recovery_stats,
132 + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
133 + "Output statistics of recovery process after it.",
134 + NULL, NULL, FALSE);
136 static MYSQL_SYSVAR_BOOL(recovery_update_relay_log, innobase_overwrite_relay_log_info,
137 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
138 "During InnoDB crash recovery on slave overwrite relay-log.info "
139 @@ -11870,6 +11878,7 @@
140 MYSQL_SYSVAR(data_file_path),
141 MYSQL_SYSVAR(data_home_dir),
142 MYSQL_SYSVAR(doublewrite),
143 + MYSQL_SYSVAR(recovery_stats),
144 MYSQL_SYSVAR(fast_shutdown),
145 MYSQL_SYSVAR(file_io_threads),
146 MYSQL_SYSVAR(read_io_threads),
147 --- a/storage/innobase/include/log0recv.h
148 +++ b/storage/innobase/include/log0recv.h
150 hash_table_t* addr_hash;/*!< hash table of file addresses of pages */
151 ulint n_addrs;/*!< number of not processed hashed file
152 addresses in the hash table */
154 +/* If you modified the following defines at original file,
155 + You should also modify them. */
156 +/* defined in os0file.c */
157 +#define OS_AIO_MERGE_N_CONSECUTIVE 64
158 +/* defined in log0recv.c */
159 +#define RECV_READ_AHEAD_AREA 32
160 + time_t stats_recv_start_time;
161 + ulint stats_recv_turns;
163 + ulint stats_read_requested_pages;
164 + ulint stats_read_in_area[RECV_READ_AHEAD_AREA];
166 + ulint stats_read_io_pages;
167 + ulint stats_read_io_consecutive[OS_AIO_MERGE_N_CONSECUTIVE];
168 + ulint stats_write_io_pages;
169 + ulint stats_write_io_consecutive[OS_AIO_MERGE_N_CONSECUTIVE];
171 + ulint stats_doublewrite_check_pages;
172 + ulint stats_doublewrite_overwrite_pages;
174 + ulint stats_recover_pages_with_read;
175 + ulint stats_recover_pages_without_read;
177 + ulint stats_log_recs;
178 + ulint stats_log_len_sum;
180 + ulint stats_applied_log_recs;
181 + ulint stats_applied_log_len_sum;
182 + ulint stats_pages_already_new;
184 + ib_uint64_t stats_oldest_modified_lsn;
185 + ib_uint64_t stats_newest_modified_lsn;
188 /** The recovery system */
189 --- a/storage/innobase/include/srv0srv.h
190 +++ b/storage/innobase/include/srv0srv.h
192 extern ulint* srv_data_file_sizes;
193 extern ulint* srv_data_file_is_raw_partition;
195 +extern ibool srv_recovery_stats;
197 extern ibool srv_auto_extend_last_data_file;
198 extern ulint srv_last_file_size_max;
199 extern char** srv_log_group_home_dirs;
200 --- a/storage/innobase/log/log0recv.c
201 +++ b/storage/innobase/log/log0recv.c
204 recv_sys->heap = NULL;
205 recv_sys->addr_hash = NULL;
207 + recv_sys->stats_recv_start_time = time(NULL);
208 + recv_sys->stats_oldest_modified_lsn = IB_ULONGLONG_MAX;
211 /********************************************************//**
213 recv_n_pool_free_frames = 512;
216 + if (buf_pool_get_curr_size() >= (32 * 1024 * 1024)) {
217 + /* Buffer pool of size greater than 32 MB. */
218 + recv_n_pool_free_frames = 1024;
221 recv_sys->buf = ut_malloc(RECV_PARSING_BUF_SIZE);
223 recv_sys->recovered_offset = 0;
224 @@ -1363,6 +1371,11 @@
226 len = rec_end - body;
228 + if (srv_recovery_stats) {
229 + recv_sys->stats_log_recs++;
230 + recv_sys->stats_log_len_sum += len;
233 recv = mem_heap_alloc(recv_sys->heap, sizeof(recv_t));
235 recv->len = rec_end - body;
236 @@ -1474,6 +1487,7 @@
237 ib_uint64_t start_lsn;
239 ib_uint64_t page_lsn;
240 + ib_uint64_t page_lsn_orig;
241 ib_uint64_t page_newest_lsn;
242 ibool modification_to_page;
243 #ifndef UNIV_HOTBACKUP
244 @@ -1496,6 +1510,8 @@
245 buf_block_get_page_no(block));
247 if ((recv_addr == NULL)
248 + /* bugfix: http://bugs.mysql.com/bug.php?id=44140 */
249 + || (recv_addr->state == RECV_BEING_READ && !just_read_in)
250 || (recv_addr->state == RECV_BEING_PROCESSED)
251 || (recv_addr->state == RECV_PROCESSED)) {
253 @@ -1511,6 +1527,14 @@
255 recv_addr->state = RECV_BEING_PROCESSED;
257 + if (srv_recovery_stats) {
258 + if (just_read_in) {
259 + recv_sys->stats_recover_pages_with_read++;
261 + recv_sys->stats_recover_pages_without_read++;
265 mutex_exit(&(recv_sys->mutex));
268 @@ -1540,6 +1564,7 @@
270 /* Read the newest modification lsn from the page */
271 page_lsn = mach_read_from_8(page + FIL_PAGE_LSN);
272 + page_lsn_orig = page_lsn;
274 #ifndef UNIV_HOTBACKUP
275 /* It may be that the page has been modified in the buffer
276 @@ -1559,6 +1584,21 @@
277 modification_to_page = FALSE;
278 start_lsn = end_lsn = 0;
280 + if (srv_recovery_stats) {
281 + mutex_enter(&(recv_sys->mutex));
282 + if (page_lsn_orig && recv_sys->stats_oldest_modified_lsn > page_lsn_orig) {
283 + recv_sys->stats_oldest_modified_lsn = page_lsn_orig;
285 + if (page_lsn_orig && recv_sys->stats_newest_modified_lsn < page_lsn_orig) {
286 + recv_sys->stats_newest_modified_lsn = page_lsn_orig;
288 + if (UT_LIST_GET_LAST(recv_addr->rec_list)->start_lsn
290 + recv_sys->stats_pages_already_new++;
292 + mutex_exit(&(recv_sys->mutex));
295 recv = UT_LIST_GET_FIRST(recv_addr->rec_list);
298 @@ -1613,6 +1653,13 @@
302 + if (srv_recovery_stats) {
303 + mutex_enter(&(recv_sys->mutex));
304 + recv_sys->stats_applied_log_recs++;
305 + recv_sys->stats_applied_log_len_sum += recv->len;
306 + mutex_exit(&(recv_sys->mutex));
309 end_lsn = recv->start_lsn + recv->len;
310 mach_write_to_8(FIL_PAGE_LSN + page, end_lsn);
311 mach_write_to_8(UNIV_PAGE_SIZE
312 @@ -1715,6 +1762,13 @@
316 + if (srv_recovery_stats && n) {
317 + mutex_enter(&(recv_sys->mutex));
318 + recv_sys->stats_read_requested_pages += n;
319 + recv_sys->stats_read_in_area[n - 1]++;
320 + mutex_exit(&(recv_sys->mutex));
323 buf_read_recv_pages(FALSE, space, zip_size, page_nos, n);
325 fprintf(stderr, "Recv pages at %lu n %lu\n", page_nos[0], n);
326 @@ -1867,6 +1921,10 @@
329 fprintf(stderr, "InnoDB: Apply batch completed\n");
331 + if (srv_recovery_stats) {
332 + recv_sys->stats_recv_turns++;
336 mutex_exit(&(recv_sys->mutex));
337 @@ -3270,6 +3328,90 @@
339 #endif /* UNIV_DEBUG */
341 + if (recv_needed_recovery && srv_recovery_stats) {
342 + ulint flush_list_len = 0;
346 + "InnoDB: Log records have been applied. The statistics that were gathered follow.\n");
349 + "============================================================\n"
350 + "-------------------\n"
351 + "RECOVERY STATISTICS\n"
352 + "-------------------\n");
354 + "Recovery time: %g sec. (%lu turns)\n",
355 + difftime(time(NULL), recv_sys->stats_recv_start_time),
356 + recv_sys->stats_recv_turns);
358 + for (i = 0; i < srv_buf_pool_instances; i++) {
359 + buf_pool_t* buf_pool;
361 + buf_pool = buf_pool_from_array(i);
362 + flush_list_len += UT_LIST_GET_LEN(buf_pool->flush_list);
366 + "Data page IO statistics\n"
367 + " Requested pages: %lu\n"
368 + " Read pages: %lu\n"
369 + " Written pages: %lu\n"
370 + " (Dirty blocks): %lu\n",
371 + recv_sys->stats_read_requested_pages,
372 + recv_sys->stats_read_io_pages,
373 + recv_sys->stats_write_io_pages,
377 + " Grouping IO [times]:\n"
378 + "\tnumber of pages,\n"
379 + "\t\tread request neighbors (in %d pages chunk),\n"
380 + "\t\t\tcombined read IO,\n"
381 + "\t\t\t\tcombined write IO\n",
382 + RECV_READ_AHEAD_AREA);
383 + for (i = 0; i < ut_max(RECV_READ_AHEAD_AREA,
384 + OS_AIO_MERGE_N_CONSECUTIVE); i++) {
386 + "\t%3lu,\t%lu,\t%lu,\t%lu\n", i + 1,
387 + (i < RECV_READ_AHEAD_AREA) ?
388 + recv_sys->stats_read_in_area[i] : 0,
389 + (i < OS_AIO_MERGE_N_CONSECUTIVE) ?
390 + recv_sys->stats_read_io_consecutive[i] : 0,
391 + (i < OS_AIO_MERGE_N_CONSECUTIVE) ?
392 + recv_sys->stats_write_io_consecutive[i] : 0);
397 + "Recovery process statistics\n"
398 + " Checked pages by doublewrite buffer: %lu\n"
399 + " Overwritten pages from doublewrite: %lu\n"
400 + " Recovered pages by io_thread: %lu\n"
401 + " Recovered pages by main thread: %lu\n"
402 + " Parsed log records to apply: %lu\n"
403 + " Sum of the length: %lu\n"
404 + " Applied log records: %lu\n"
405 + " Sum of the length: %lu\n"
406 + " Pages which are already new enough: %lu (It may not be accurate, if turns > 1)\n"
407 + " Oldest page's LSN: %llu\n"
408 + " Newest page's LSN: %llu\n",
409 + recv_sys->stats_doublewrite_check_pages,
410 + recv_sys->stats_doublewrite_overwrite_pages,
411 + recv_sys->stats_recover_pages_with_read,
412 + recv_sys->stats_recover_pages_without_read,
413 + recv_sys->stats_log_recs,
414 + recv_sys->stats_log_len_sum,
415 + recv_sys->stats_applied_log_recs,
416 + recv_sys->stats_applied_log_len_sum,
417 + recv_sys->stats_pages_already_new,
418 + recv_sys->stats_oldest_modified_lsn,
419 + recv_sys->stats_newest_modified_lsn);
422 + "============================================================\n");
425 if (recv_needed_recovery) {
426 trx_sys_print_mysql_master_log_pos();
427 trx_sys_print_mysql_binlog_offset();
428 --- a/storage/innobase/os/os0file.c
429 +++ b/storage/innobase/os/os0file.c
431 #include "srv0start.h"
434 +#include "log0recv.h"
435 #ifndef UNIV_HOTBACKUP
436 # include "os0sync.h"
437 # include "os0thread.h"
438 @@ -4278,6 +4279,18 @@
442 + if (srv_recovery_stats && recv_recovery_is_on() && n_consecutive) {
443 + mutex_enter(&(recv_sys->mutex));
444 + if (slot->type == OS_FILE_READ) {
445 + recv_sys->stats_read_io_pages += n_consecutive;
446 + recv_sys->stats_read_io_consecutive[n_consecutive - 1]++;
447 + } else if (slot->type == OS_FILE_WRITE) {
448 + recv_sys->stats_write_io_pages += n_consecutive;
449 + recv_sys->stats_write_io_consecutive[n_consecutive - 1]++;
451 + mutex_exit(&(recv_sys->mutex));
454 os_mutex_enter(array->mutex);
456 if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS
457 --- a/storage/innobase/srv/srv0srv.c
458 +++ b/storage/innobase/srv/srv0srv.c
460 /* size in database pages */
461 UNIV_INTERN ulint* srv_data_file_sizes = NULL;
463 +UNIV_INTERN ibool srv_recovery_stats = FALSE;
465 /* if TRUE, then we auto-extend the last data file */
466 UNIV_INTERN ibool srv_auto_extend_last_data_file = FALSE;
467 /* if != 0, this tells the max size auto-extending may increase the
468 --- a/storage/innobase/trx/trx0sys.c
469 +++ b/storage/innobase/trx/trx0sys.c
471 zip_size ? zip_size : UNIV_PAGE_SIZE,
474 + if (srv_recovery_stats && recv_recovery_is_on()) {
475 + mutex_enter(&(recv_sys->mutex));
476 + recv_sys->stats_doublewrite_check_pages++;
477 + mutex_exit(&(recv_sys->mutex));
480 /* Check if the page is corrupt */
484 zip_size, page_no, 0,
485 zip_size ? zip_size : UNIV_PAGE_SIZE,
488 + if (srv_recovery_stats && recv_recovery_is_on()) {
489 + mutex_enter(&(recv_sys->mutex));
490 + recv_sys->stats_doublewrite_overwrite_pages++;
491 + mutex_exit(&(recv_sys->mutex));
495 "InnoDB: Recovered the page from"
496 " the doublewrite buffer.\n");