1
1
/*****************************************************************************
3
Copyright (C) 1997, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
138
138
/** This many frames must be left free in the buffer pool when we scan
139
139
the log and store the scanned log records in the buffer pool: we will
140
140
use these free frames to read in pages when we start applying the
141
log records to the database.
142
This is the default value. If the actual size of the buffer pool is
143
larger than 10 MB we'll set this value to 512. */
141
log records to the database. */
144
142
UNIV_INTERN ulint recv_n_pool_free_frames;
146
144
/** The maximum lsn we see for a page during the recovery process. If this
148
146
the recovery failed and the database may be corrupt. */
149
147
UNIV_INTERN ib_uint64_t recv_max_page_lsn;
151
#ifdef UNIV_PFS_THREAD
152
UNIV_INTERN mysql_pfs_key_t trx_rollback_clean_thread_key;
153
#endif /* UNIV_PFS_THREAD */
155
#ifdef UNIV_PFS_MUTEX
156
UNIV_INTERN mysql_pfs_key_t recv_sys_mutex_key;
157
#endif /* UNIV_PFS_MUTEX */
161
151
#ifndef UNIV_HOTBACKUP
183
recv_sys = static_cast<recv_sys_t *>(mem_alloc(sizeof(*recv_sys)));
173
recv_sys = mem_alloc(sizeof(*recv_sys));
184
174
memset(recv_sys, 0x0, sizeof(*recv_sys));
186
mutex_create(recv_sys_mutex_key, &recv_sys->mutex, SYNC_RECV);
176
mutex_create(&recv_sys->mutex, SYNC_RECV);
188
178
recv_sys->heap = NULL;
189
179
recv_sys->addr_hash = NULL;
307
#ifndef UNIV_HOTBACKUP
308
/* Initialize red-black tree for fast insertions into the
309
flush_list during recovery process.
310
As this initialization is done while holding the buffer pool
311
mutex we perform it before acquiring recv_sys->mutex. */
312
#ifndef UNIV_HOTBACKUP
313
buf_flush_init_flush_rbt();
314
#endif /* !UNIV_HOTBACKUP */
316
295
mutex_enter(&(recv_sys->mutex));
297
#ifndef UNIV_HOTBACKUP
318
298
recv_sys->heap = mem_heap_create_in_buffer(256);
319
299
#else /* !UNIV_HOTBACKUP */
320
300
recv_sys->heap = mem_heap_create(256);
321
301
recv_is_from_backup = TRUE;
322
302
#endif /* !UNIV_HOTBACKUP */
324
/* Set appropriate value of recv_n_pool_free_frames. */
325
if (buf_pool_get_curr_size() >= (10 * 1024 * 1024)) {
326
/* Buffer pool of size greater than 10 MB. */
327
recv_n_pool_free_frames = 512;
330
recv_sys->buf = static_cast<byte *>(ut_malloc(RECV_PARSING_BUF_SIZE));
304
recv_sys->buf = ut_malloc(RECV_PARSING_BUF_SIZE);
331
305
recv_sys->len = 0;
332
306
recv_sys->recovered_offset = 0;
334
recv_sys->addr_hash = hash_create(available_memory / 512);
308
recv_sys->addr_hash = hash_create(available_memory / 64);
335
309
recv_sys->n_addrs = 0;
337
311
recv_sys->apply_log_recs = FALSE;
338
312
recv_sys->apply_batch_on = FALSE;
340
recv_sys->last_block_buf_start = static_cast<byte *>(mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE));
314
recv_sys->last_block_buf_start = mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE);
342
recv_sys->last_block = static_cast<byte *>(ut_align(recv_sys->last_block_buf_start,
343
OS_FILE_LOG_BLOCK_SIZE));
316
recv_sys->last_block = ut_align(recv_sys->last_block_buf_start,
317
OS_FILE_LOG_BLOCK_SIZE);
344
318
recv_sys->found_corrupt_log = FALSE;
346
320
recv_max_page_lsn = 0;
371
345
hash_table_free(recv_sys->addr_hash);
372
346
mem_heap_empty(recv_sys->heap);
374
recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 512);
348
recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 256);
377
351
#ifndef UNIV_HOTBACKUP
396
370
recv_sys->last_block_buf_start = NULL;
398
372
mutex_exit(&(recv_sys->mutex));
400
/* Free up the flush_rbt. */
401
buf_flush_free_flush_rbt();
403
374
# endif /* UNIV_LOG_DEBUG */
569
540
ib_uint64_t start_lsn;
570
541
ib_uint64_t end_lsn;
571
542
ib_uint64_t recovered_lsn;
543
ib_uint64_t limit_lsn;
573
545
recovered_lsn = recv_sys->recovered_lsn;
546
limit_lsn = recv_sys->limit_lsn;
575
548
/* Read the last recovered log block to the recovery system buffer:
576
549
the block is always incomplete */
703
676
group->state = LOG_GROUP_OK;
705
group->lsn = mach_read_from_8(
678
group->lsn = mach_read_ull(
706
679
buf + LOG_CHECKPOINT_LSN);
707
680
group->lsn_offset = mach_read_from_4(
708
681
buf + LOG_CHECKPOINT_OFFSET);
709
checkpoint_no = mach_read_from_8(
682
checkpoint_no = mach_read_ull(
710
683
buf + LOG_CHECKPOINT_NO);
712
685
#ifdef UNIV_DEBUG
776
749
cp_buf = hdr + LOG_CHECKPOINT_1;
778
751
if (recv_check_cp_is_consistent(cp_buf)) {
779
max_cp_no = mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO);
752
max_cp_no = mach_read_ull(cp_buf + LOG_CHECKPOINT_NO);
780
753
max_cp = LOG_CHECKPOINT_1;
783
756
cp_buf = hdr + LOG_CHECKPOINT_2;
785
758
if (recv_check_cp_is_consistent(cp_buf)) {
786
if (mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO) > max_cp_no) {
759
if (mach_read_ull(cp_buf + LOG_CHECKPOINT_NO) > max_cp_no) {
787
760
max_cp = LOG_CHECKPOINT_2;
795
768
cp_buf = hdr + max_cp;
797
*lsn = mach_read_from_8(cp_buf + LOG_CHECKPOINT_LSN);
770
*lsn = mach_read_ull(cp_buf + LOG_CHECKPOINT_LSN);
798
771
*offset = mach_read_from_4(cp_buf + LOG_CHECKPOINT_OFFSET);
800
773
/* If the user is running a pre-3.23.50 version of InnoDB, its
815
788
/* fprintf(stderr, "fsp limit %lu MB\n", *fsp_limit); */
817
*cp_no = mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO);
790
*cp_no = mach_read_ull(cp_buf + LOG_CHECKPOINT_NO);
819
*first_header_lsn = mach_read_from_8(hdr + LOG_FILE_START_LSN);
792
*first_header_lsn = mach_read_ull(hdr + LOG_FILE_START_LSN);
1320
1293
recv_addr_t* recv_addr;
1322
recv_addr = static_cast<recv_addr_t *>(HASH_GET_FIRST(recv_sys->addr_hash,
1323
recv_hash(space, page_no)));
1295
recv_addr = HASH_GET_FIRST(recv_sys->addr_hash,
1296
recv_hash(space, page_no));
1324
1297
while (recv_addr) {
1325
1298
if ((recv_addr->space == space)
1326
1299
&& (recv_addr->page_no == page_no)) {
1364
1337
len = rec_end - body;
1366
recv = static_cast<recv_t *>(mem_heap_alloc(recv_sys->heap, sizeof(recv_t)));
1339
recv = mem_heap_alloc(recv_sys->heap, sizeof(recv_t));
1367
1340
recv->type = type;
1368
1341
recv->len = rec_end - body;
1369
1342
recv->start_lsn = start_lsn;
1372
1345
recv_addr = recv_get_fil_addr_struct(space, page_no);
1374
1347
if (recv_addr == NULL) {
1375
recv_addr = static_cast<recv_addr_t *>(mem_heap_alloc(recv_sys->heap,
1376
sizeof(recv_addr_t)));
1348
recv_addr = mem_heap_alloc(recv_sys->heap,
1349
sizeof(recv_addr_t));
1377
1350
recv_addr->space = space;
1378
1351
recv_addr->page_no = page_no;
1379
1352
recv_addr->state = RECV_NOT_PROCESSED;
1405
1378
len = RECV_DATA_BLOCK_SIZE;
1408
recv_data = static_cast<recv_data_t *>(mem_heap_alloc(recv_sys->heap,
1409
sizeof(recv_data_t) + len));
1381
recv_data = mem_heap_alloc(recv_sys->heap,
1382
sizeof(recv_data_t) + len);
1410
1383
*prev_field = recv_data;
1412
1385
memcpy(recv_data + 1, body, len);
1539
1512
#endif /* !UNIV_HOTBACKUP */
1541
1514
/* Read the newest modification lsn from the page */
1542
page_lsn = mach_read_from_8(page + FIL_PAGE_LSN);
1515
page_lsn = mach_read_ull(page + FIL_PAGE_LSN);
1544
1517
#ifndef UNIV_HOTBACKUP
1545
1518
/* It may be that the page has been modified in the buffer
1568
1541
/* We have to copy the record body to a separate
1571
buf = static_cast<byte *>(mem_alloc(recv->len));
1544
buf = mem_alloc(recv->len);
1573
1546
recv_data_copy_to_buf(buf, recv);
1613
1586
buf + recv->len,
1616
page_end_lsn = recv->start_lsn + recv->len;
1617
mach_write_to_8(FIL_PAGE_LSN + page, page_end_lsn);
1618
mach_write_to_8(UNIV_PAGE_SIZE
1619
- FIL_PAGE_END_LSN_OLD_CHKSUM
1620
+ page, page_end_lsn);
1589
end_lsn = recv->start_lsn + recv->len;
1590
mach_write_ull(FIL_PAGE_LSN + page, end_lsn);
1591
mach_write_ull(UNIV_PAGE_SIZE
1592
- FIL_PAGE_END_LSN_OLD_CHKSUM
1622
1595
if (page_zip) {
1623
mach_write_to_8(FIL_PAGE_LSN
1624
+ page_zip->data, page_end_lsn);
1596
mach_write_ull(FIL_PAGE_LSN
1597
+ page_zip->data, end_lsn);
1659
1632
if (modification_to_page) {
1662
log_flush_order_mutex_enter();
1663
1635
buf_flush_recv_note_modification(block, start_lsn, end_lsn);
1664
log_flush_order_mutex_exit();
1666
1637
#endif /* !UNIV_HOTBACKUP */
1768
1739
for (i = 0; i < hash_get_n_cells(recv_sys->addr_hash); i++) {
1770
recv_addr = static_cast<recv_addr_t *>(HASH_GET_FIRST(recv_sys->addr_hash, i));
1741
recv_addr = HASH_GET_FIRST(recv_sys->addr_hash, i);
1772
1743
while (recv_addr) {
1773
1744
ulint space = recv_addr->space;
1846
1817
mutex_exit(&(recv_sys->mutex));
1847
1818
mutex_exit(&(log_sys->mutex));
1849
n_pages = buf_flush_list(ULINT_MAX, IB_ULONGLONG_MAX);
1850
ut_a(n_pages != ULINT_UNDEFINED);
1852
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
1820
n_pages = buf_flush_batch(BUF_FLUSH_LIST, ULINT_MAX,
1822
ut_a(n_pages != ULINT_UNDEFINED);
1824
buf_flush_wait_batch_end(BUF_FLUSH_LIST);
1854
1826
buf_pool_invalidate();
1990
1962
buf_flush_init_for_writing(
1991
1963
block->frame, buf_block_get_page_zip(block),
1992
mach_read_from_8(block->frame + FIL_PAGE_LSN));
1964
mach_read_ull(block->frame + FIL_PAGE_LSN));
1994
1966
if (zip_size) {
1995
1967
error = fil_io(OS_FILE_WRITE, TRUE,
2079
2051
#endif /* UNIV_LOG_LSN_DEBUG */
2053
/* Check that page_no is sensible */
2055
if (UNIV_UNLIKELY(*page_no > 0x8FFFFFFFUL)) {
2057
recv_sys->found_corrupt_log = TRUE;
2081
2062
new_ptr = recv_parse_or_apply_log_rec_body(*type, new_ptr, end_ptr,
2083
2064
if (UNIV_UNLIKELY(new_ptr == NULL)) {
2186
2167
putc('\n', stderr);
2189
#ifndef UNIV_HOTBACKUP
2190
if (!srv_force_recovery) {
2191
fputs("InnoDB: Set innodb_force_recovery"
2192
" to ignore this error.\n", stderr);
2195
#endif /* !UNIV_HOTBACKUP */
2197
2170
fputs("InnoDB: WARNING: the log file may have been corrupt and it\n"
2198
2171
"InnoDB: is possible that the log scan did not proceed\n"
2199
2172
"InnoDB: far enough in recovery! Please run CHECK TABLE\n"
2709
2682
recv_sys->found_corrupt_log = TRUE;
2711
#ifndef UNIV_HOTBACKUP
2712
if (!srv_force_recovery) {
2714
" innodb_force_recovery"
2715
" to ignore this error.\n",
2719
#endif /* !UNIV_HOTBACKUP */
2721
2684
} else if (!recv_sys->found_corrupt_log) {
2722
2685
more_data = recv_sys_add_to_parsing_buf(
2723
2686
log_block, scanned_lsn);
2759
2722
recv_parse_log_recs(store_to_hash);
2761
2724
#ifndef UNIV_HOTBACKUP
2763
&& mem_heap_get_size(recv_sys->heap) > available_memory) {
2725
if (store_to_hash && mem_heap_get_size(recv_sys->heap)
2726
> available_memory) {
2765
2728
/* Hash table of log records has grown too big:
2766
2729
empty it; FALSE means no ibuf operations
2812
2775
group, start_lsn, end_lsn);
2814
2777
finished = recv_scan_log_recs(
2815
(buf_pool_get_n_pages()
2816
- (recv_n_pool_free_frames * srv_buf_pool_instances))
2818
TRUE, log_sys->buf, RECV_SCAN_SIZE,
2778
(buf_pool->curr_size - recv_n_pool_free_frames)
2779
* UNIV_PAGE_SIZE, TRUE, log_sys->buf, RECV_SCAN_SIZE,
2819
2780
start_lsn, contiguous_lsn, group_scanned_lsn);
2820
2781
start_lsn = end_lsn;
2902
2863
ib_uint64_t old_scanned_lsn;
2903
2864
ib_uint64_t group_scanned_lsn= 0;
2904
2865
ib_uint64_t contiguous_lsn;
2905
#ifdef UNIV_LOG_ARCHIVE
2906
2866
ib_uint64_t archived_lsn;
2907
#endif /* UNIV_LOG_ARCHIVE */
2909
2868
byte log_hdr_buf[LOG_FILE_HDR_SIZE];
2958
2917
buf = log_sys->checkpoint_buf;
2960
checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
2961
checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
2962
#ifdef UNIV_LOG_ARCHIVE
2963
archived_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN);
2964
#endif /* UNIV_LOG_ARCHIVE */
2919
checkpoint_lsn = mach_read_ull(buf + LOG_CHECKPOINT_LSN);
2920
checkpoint_no = mach_read_ull(buf + LOG_CHECKPOINT_NO);
2921
archived_lsn = mach_read_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN);
2966
2923
/* Read the first log file header to print a note if this is
2967
2924
a recovery from a restored InnoDB Hot Backup */
3295
3259
The data dictionary latch should guarantee that there is at
3296
3260
most one data dictionary transaction active at a time. */
3297
3261
trx_rollback_or_clean_recovered(FALSE);
3300
/********************************************************//**
3301
Initiates the rollback of active transactions. */
3304
recv_recovery_rollback_active(void)
3305
/*===============================*/
3263
/* Drop partially created indexes. */
3264
row_merge_drop_temp_indexes();
3309
3266
#ifdef UNIV_SYNC_DEBUG
3310
3267
/* Wait for a while so that created threads have time to suspend
3314
3271
/* Switch latching order checks on in sync0sync.c */
3315
3272
sync_order_checks_on = TRUE;
3317
/* Drop partially created indexes. */
3318
row_merge_drop_temp_indexes();
3319
/* Drop temporary tables. */
3320
row_mysql_drop_temp_tables();
3322
3274
if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) {
3323
3275
/* Rollback the uncommitted transactions which have no user
3434
3386
sprintf(name, "%s%s%lu", log_dir,
3435
3387
ib_logfile_basename, (ulong)i);
3437
log_file = os_file_create_simple(innodb_file_log_key,
3438
name, OS_FILE_CREATE,
3389
log_file = os_file_create_simple(name, OS_FILE_CREATE,
3390
OS_FILE_READ_WRITE, &success);
3441
3391
if (!success) {
3442
3392
fprintf(stderr,
3443
3393
"InnoDB: Cannot create %s. Check that"
3476
3426
LOG_BLOCK_HDR_SIZE);
3477
3427
sprintf(name, "%s%s%lu", log_dir, ib_logfile_basename, (ulong)0);
3479
log_file = os_file_create_simple(innodb_file_log_key,
3429
log_file = os_file_create_simple(name, OS_FILE_OPEN,
3481
3430
OS_FILE_READ_WRITE, &success);
3482
3431
if (!success) {
3483
3432
fprintf(stderr, "InnoDB: Cannot open %s.\n", name);
3495
3444
#endif /* UNIV_HOTBACKUP */
3497
3446
#ifdef UNIV_LOG_ARCHIVE
3499
3447
/******************************************************//**
3500
3448
Reads from the archive of a log group and performs recovery.
3501
3449
@return TRUE if no more complete consistent archive files */
3529
3477
log_archived_file_name_gen(name, group->id, group->archived_file_no);
3531
file_handle = os_file_create(innodb_file_log_key,
3479
file_handle = os_file_create(name, OS_FILE_OPEN,
3533
3480
OS_FILE_LOG, OS_FILE_AIO, &ret);
3535
3482
if (ret == FALSE) {
3609
start_lsn = mach_read_from_8(buf + LOG_FILE_START_LSN);
3610
file_end_lsn = mach_read_from_8(buf + LOG_FILE_END_LSN);
3556
start_lsn = mach_read_ull(buf + LOG_FILE_START_LSN);
3557
file_end_lsn = mach_read_ull(buf + LOG_FILE_END_LSN);
3612
3559
if (!recv_sys->scanned_lsn) {
3661
3608
read_offset % UNIV_PAGE_SIZE, len, buf, NULL);
3663
3610
ret = recv_scan_log_recs(
3664
(buf_pool_get_n_pages()
3665
- (recv_n_pool_free_frames * srv_buf_pool_instances))
3611
(buf_pool->n_frames - recv_n_pool_free_frames)
3666
3612
* UNIV_PAGE_SIZE, TRUE, buf, len, start_lsn,
3667
3613
&dummy_lsn, &scanned_lsn);