49
51
/* Read-ahead area in applying log records to file pages */
50
52
#define RECV_READ_AHEAD_AREA 32
52
recv_sys_t* recv_sys = NULL;
53
ibool recv_recovery_on = FALSE;
54
ibool recv_recovery_from_backup_on = FALSE;
56
ibool recv_needed_recovery = FALSE;
58
ibool recv_lsn_checks_on = FALSE;
54
UNIV_INTERN recv_sys_t* recv_sys = NULL;
55
UNIV_INTERN ibool recv_recovery_on = FALSE;
56
UNIV_INTERN ibool recv_recovery_from_backup_on = FALSE;
58
UNIV_INTERN ibool recv_needed_recovery = FALSE;
60
UNIV_INTERN ibool recv_lsn_checks_on = FALSE;
60
62
/* There are two conditions under which we scan the logs, the first
61
63
is normal startup and the second is when we do a recovery from an
77
79
/* Recovery is running and no operations on the log files are allowed
78
80
yet: the variable name is misleading */
80
ibool recv_no_ibuf_operations = FALSE;
82
UNIV_INTERN ibool recv_no_ibuf_operations = FALSE;
82
84
/* The following counter is used to decide when to print info on
84
ulint recv_scan_print_counter = 0;
86
UNIV_INTERN ulint recv_scan_print_counter = 0;
86
ibool recv_is_from_backup = FALSE;
88
UNIV_INTERN ibool recv_is_from_backup = FALSE;
87
89
#ifdef UNIV_HOTBACKUP
88
ibool recv_is_making_a_backup = FALSE;
90
UNIV_INTERN ibool recv_is_making_a_backup = FALSE;
90
92
# define recv_is_making_a_backup FALSE
91
93
#endif /* UNIV_HOTBACKUP */
93
ulint recv_previous_parsed_rec_type = 999999;
94
ulint recv_previous_parsed_rec_offset = 0;
95
ulint recv_previous_parsed_rec_is_multi = 0;
95
UNIV_INTERN ulint recv_previous_parsed_rec_type = 999999;
96
UNIV_INTERN ulint recv_previous_parsed_rec_offset = 0;
97
UNIV_INTERN ulint recv_previous_parsed_rec_is_multi = 0;
97
ulint recv_max_parsed_page_no = 0;
99
UNIV_INTERN ulint recv_max_parsed_page_no = 0;
99
101
/* This many frames must be left free in the buffer pool when we scan
100
102
the log and store the scanned log records in the buffer pool: we will
101
103
use these free frames to read in pages when we start applying the
102
104
log records to the database. */
104
ulint recv_n_pool_free_frames = 256;
106
UNIV_INTERN ulint recv_n_pool_free_frames = 256;
106
108
/* The maximum lsn we see for a page during the recovery process. If this
107
109
is bigger than the lsn we are able to scan up to, that is an indication that
108
110
the recovery failed and the database may be corrupt. */
110
dulint recv_max_page_lsn;
112
UNIV_INTERN ib_uint64_t recv_max_page_lsn;
239
241
recv_truncate_group(
240
242
/*================*/
241
243
log_group_t* group, /* in: log group */
242
dulint recovered_lsn, /* in: recovery succeeded up to this
244
ib_uint64_t recovered_lsn, /* in: recovery succeeded up to this
244
dulint limit_lsn, /* in: this was the limit for
246
ib_uint64_t limit_lsn, /* in: this was the limit for
246
dulint checkpoint_lsn, /* in: recovery was started from this
248
ib_uint64_t checkpoint_lsn, /* in: recovery was started from this
248
dulint archived_lsn) /* in: the log has been archived up to
250
ib_uint64_t archived_lsn) /* in: the log has been archived up to
253
ib_uint64_t start_lsn;
255
ib_uint64_t finish_lsn1;
256
ib_uint64_t finish_lsn2;
257
ib_uint64_t finish_lsn;
259
if (ut_dulint_cmp(archived_lsn, ut_dulint_max) == 0) {
261
if (archived_lsn == IB_ULONGLONG_MAX) {
260
262
/* Checkpoint was taken in the NOARCHIVELOG mode */
261
263
archived_lsn = checkpoint_lsn;
264
finish_lsn1 = ut_dulint_add(ut_dulint_align_down(
266
OS_FILE_LOG_BLOCK_SIZE),
267
log_group_get_capacity(group));
269
finish_lsn2 = ut_dulint_add(ut_dulint_align_up(
271
OS_FILE_LOG_BLOCK_SIZE),
272
recv_sys->last_log_buf_size);
274
if (ut_dulint_cmp(limit_lsn, ut_dulint_max) != 0) {
266
finish_lsn1 = ut_uint64_align_down(archived_lsn,
267
OS_FILE_LOG_BLOCK_SIZE)
268
+ log_group_get_capacity(group);
270
finish_lsn2 = ut_uint64_align_up(recovered_lsn,
271
OS_FILE_LOG_BLOCK_SIZE)
272
+ recv_sys->last_log_buf_size;
274
if (limit_lsn != IB_ULONGLONG_MAX) {
275
275
/* We do not know how far we should erase log records: erase
276
276
as much as possible */
278
278
finish_lsn = finish_lsn1;
280
280
/* It is enough to erase the length of the log buffer */
281
finish_lsn = ut_dulint_get_min(finish_lsn1, finish_lsn2);
281
finish_lsn = finish_lsn1 < finish_lsn2
282
? finish_lsn1 : finish_lsn2;
284
285
ut_a(RECV_SCAN_SIZE <= log_sys->buf_size);
289
290
*(log_sys->buf + i) = '\0';
292
start_lsn = ut_dulint_align_down(recovered_lsn,
293
start_lsn = ut_uint64_align_down(recovered_lsn,
293
294
OS_FILE_LOG_BLOCK_SIZE);
295
if (ut_dulint_cmp(start_lsn, recovered_lsn) != 0) {
296
if (start_lsn != recovered_lsn) {
296
297
/* Copy the last incomplete log block to the log buffer and
297
298
edit its data length: */
299
300
ut_memcpy(log_sys->buf, recv_sys->last_block,
300
301
OS_FILE_LOG_BLOCK_SIZE);
301
log_block_set_data_len(log_sys->buf, ut_dulint_minus(
302
recovered_lsn, start_lsn));
302
log_block_set_data_len(log_sys->buf,
303
(ulint) (recovered_lsn - start_lsn));
305
if (ut_dulint_cmp(start_lsn, finish_lsn) >= 0) {
306
if (start_lsn >= finish_lsn) {
311
end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE);
312
end_lsn = start_lsn + RECV_SCAN_SIZE;
313
if (ut_dulint_cmp(end_lsn, finish_lsn) > 0) {
314
if (end_lsn > finish_lsn) {
315
316
end_lsn = finish_lsn;
318
len = ut_dulint_minus(end_lsn, start_lsn);
319
len = (ulint) (end_lsn - start_lsn);
320
321
log_group_write_buf(group, log_sys->buf, len, start_lsn, 0);
321
if (ut_dulint_cmp(end_lsn, finish_lsn) >= 0) {
322
if (end_lsn >= finish_lsn) {
345
346
log_group_t* group, /* in: copy to this log
347
dulint recovered_lsn) /* in: recovery succeeded up
348
ib_uint64_t recovered_lsn) /* in: recovery succeeded up
351
ib_uint64_t start_lsn;
354
if (ut_dulint_cmp(group->scanned_lsn, recovered_lsn) >= 0) {
355
if (group->scanned_lsn >= recovered_lsn) {
359
360
ut_a(RECV_SCAN_SIZE <= log_sys->buf_size);
361
start_lsn = ut_dulint_align_down(group->scanned_lsn,
362
start_lsn = ut_uint64_align_down(group->scanned_lsn,
362
363
OS_FILE_LOG_BLOCK_SIZE);
364
end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE);
365
end_lsn = start_lsn + RECV_SCAN_SIZE;
366
if (ut_dulint_cmp(end_lsn, recovered_lsn) > 0) {
367
end_lsn = ut_dulint_align_up(recovered_lsn,
367
if (end_lsn > recovered_lsn) {
368
end_lsn = ut_uint64_align_up(recovered_lsn,
368
369
OS_FILE_LOG_BLOCK_SIZE);
371
372
log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
372
373
up_to_date_group, start_lsn, end_lsn);
374
len = ut_dulint_minus(end_lsn, start_lsn);
375
len = (ulint) (end_lsn - start_lsn);
376
377
log_group_write_buf(group, log_sys->buf, len, start_lsn, 0);
378
if (ut_dulint_cmp(end_lsn, recovered_lsn) >= 0) {
379
if (end_lsn >= recovered_lsn) {
408
409
/* Read the last recovered log block to the recovery system buffer:
409
410
the block is always incomplete */
411
start_lsn = ut_dulint_align_down(recovered_lsn,
412
start_lsn = ut_uint64_align_down(recovered_lsn,
412
413
OS_FILE_LOG_BLOCK_SIZE);
413
end_lsn = ut_dulint_align_up(recovered_lsn, OS_FILE_LOG_BLOCK_SIZE);
414
end_lsn = ut_uint64_align_up(recovered_lsn, OS_FILE_LOG_BLOCK_SIZE);
415
ut_a(ut_dulint_cmp(start_lsn, end_lsn) != 0);
416
ut_a(start_lsn != end_lsn);
417
418
log_group_read_log_seg(LOG_RECOVER, recv_sys->last_block,
418
419
up_to_date_group, start_lsn, end_lsn);
586
586
/***********************************************************************
587
587
Reads the checkpoint info needed in hot backup. */
590
590
recv_read_cp_info_for_backup(
591
591
/*=========================*/
592
/* out: TRUE if success */
593
byte* hdr, /* in: buffer containing the log group header */
594
dulint* lsn, /* out: checkpoint lsn */
595
ulint* offset, /* out: checkpoint offset in the log group */
596
ulint* fsp_limit,/* out: fsp limit of space 0, 1000000000 if the
597
database is running with < version 3.23.50 of InnoDB */
598
dulint* cp_no, /* out: checkpoint number */
599
dulint* first_header_lsn)
600
/* out: lsn of of the start of the first log file */
592
/* out: TRUE if success */
593
byte* hdr, /* in: buffer containing the log group
595
ib_uint64_t* lsn, /* out: checkpoint lsn */
596
ulint* offset, /* out: checkpoint offset in the log group */
597
ulint* fsp_limit,/* out: fsp limit of space 0,
598
1000000000 if the database is running
599
with < version 3.23.50 of InnoDB */
600
ib_uint64_t* cp_no, /* out: checkpoint number */
601
ib_uint64_t* first_header_lsn)
602
/* out: lsn of of the start of the
603
dulint max_cp_no = ut_dulint_zero;
606
ib_uint64_t max_cp_no = 0;
606
609
cp_buf = hdr + LOG_CHECKPOINT_1;
608
611
if (recv_check_cp_is_consistent(cp_buf)) {
609
max_cp_no = mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO);
612
max_cp_no = mach_read_ull(cp_buf + LOG_CHECKPOINT_NO);
610
613
max_cp = LOG_CHECKPOINT_1;
613
616
cp_buf = hdr + LOG_CHECKPOINT_2;
615
618
if (recv_check_cp_is_consistent(cp_buf)) {
616
if (ut_dulint_cmp(mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO),
619
if (mach_read_ull(cp_buf + LOG_CHECKPOINT_NO) > max_cp_no) {
618
620
max_cp = LOG_CHECKPOINT_2;
691
693
/***********************************************************************
692
694
Scans the log segment and n_bytes_scanned is set to the length of valid
696
698
recv_scan_log_seg_for_backup(
697
699
/*=========================*/
698
700
byte* buf, /* in: buffer containing log data */
699
701
ulint buf_len, /* in: data length in that buffer */
700
dulint* scanned_lsn, /* in/out: lsn of buffer start,
702
ib_uint64_t* scanned_lsn, /* in/out: lsn of buffer start,
701
703
we return scanned lsn */
702
704
ulint* scanned_checkpoint_no,
703
705
/* in/out: 4 lowest bytes of the
786
788
recv_parse_or_apply_log_rec_body(
787
789
/*=============================*/
788
/* out: log record end, NULL if not a complete
790
byte type, /* in: type */
791
byte* ptr, /* in: pointer to a buffer */
792
byte* end_ptr,/* in: pointer to the buffer end */
793
page_t* page, /* in: buffer page or NULL; if not NULL, then the log
794
record is applied to the page, and the log record
795
should be complete then */
796
mtr_t* mtr) /* in: mtr or NULL; should be non-NULL if and only if
790
/* out: log record end, NULL if not a
792
byte type, /* in: type */
793
byte* ptr, /* in: pointer to a buffer */
794
byte* end_ptr,/* in: pointer to the buffer end */
795
buf_block_t* block, /* in/out: buffer block or NULL; if
796
not NULL, then the log record is
797
applied to the page, and the log
798
record should be complete then */
799
mtr_t* mtr) /* in: mtr or NULL; should be non-NULL
800
if and only if block is non-NULL */
799
dict_index_t* index = NULL;
802
dict_index_t* index = NULL;
804
page_zip_des_t* page_zip;
806
ut_ad(!block == !mtr);
810
page_zip = buf_block_get_page_zip(block);
802
817
case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES:
803
ptr = mlog_parse_nbytes(type, ptr, end_ptr, page);
818
ptr = mlog_parse_nbytes(type, ptr, end_ptr, page, page_zip);
805
820
case MLOG_REC_INSERT: case MLOG_COMP_REC_INSERT:
806
821
if (NULL != (ptr = mlog_parse_index(
823
838
|| (ibool)!!page_is_comp(page)
824
839
== dict_table_is_comp(index->table));
825
840
ptr = btr_cur_parse_del_mark_set_clust_rec(
826
ptr, end_ptr, index, page);
841
ptr, end_ptr, page, page_zip, index);
829
844
case MLOG_COMP_REC_SEC_DELETE_MARK:
830
845
/* This log record type is obsolete, but we process it for
831
846
backward compatibility with MySQL 5.0.3 and 5.0.4. */
832
847
ut_a(!page || page_is_comp(page));
833
849
ptr = mlog_parse_index(ptr, end_ptr, TRUE, &index);
837
853
/* Fall through */
838
854
case MLOG_REC_SEC_DELETE_MARK:
839
ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr, page);
855
ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr,
841
858
case MLOG_REC_UPDATE_IN_PLACE: case MLOG_COMP_REC_UPDATE_IN_PLACE:
842
859
if (NULL != (ptr = mlog_parse_index(
924
947
|| (ibool)!!page_is_comp(page)
925
948
== dict_table_is_comp(index->table));
926
949
ptr = page_cur_parse_delete_rec(ptr, end_ptr,
930
953
case MLOG_IBUF_BITMAP_INIT:
931
ptr = ibuf_parse_bitmap_init(ptr, end_ptr, page, mtr);
954
ptr = ibuf_parse_bitmap_init(ptr, end_ptr, block, mtr);
933
956
case MLOG_INIT_FILE_PAGE:
934
ptr = fsp_parse_init_file_page(ptr, end_ptr, page);
957
ptr = fsp_parse_init_file_page(ptr, end_ptr, block);
936
959
case MLOG_WRITE_STRING:
937
ptr = mlog_parse_string(ptr, end_ptr, page);
960
ptr = mlog_parse_string(ptr, end_ptr, page, page_zip);
939
962
case MLOG_FILE_CREATE:
940
963
case MLOG_FILE_RENAME:
941
964
case MLOG_FILE_DELETE:
942
ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE,
965
case MLOG_FILE_CREATE2:
966
ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, 0);
968
case MLOG_ZIP_WRITE_NODE_PTR:
969
ptr = page_zip_parse_write_node_ptr(ptr, end_ptr,
972
case MLOG_ZIP_WRITE_BLOB_PTR:
973
ptr = page_zip_parse_write_blob_ptr(ptr, end_ptr,
976
case MLOG_ZIP_WRITE_HEADER:
977
ptr = page_zip_parse_write_header(ptr, end_ptr,
980
case MLOG_ZIP_PAGE_COMPRESS:
981
ptr = page_zip_parse_compress(ptr, end_ptr,
1020
1059
recv_add_to_hash_table(
1021
1060
/*===================*/
1022
byte type, /* in: log record type */
1023
ulint space, /* in: space id */
1024
ulint page_no, /* in: page number */
1025
byte* body, /* in: log record body */
1026
byte* rec_end, /* in: log record end */
1027
dulint start_lsn, /* in: start lsn of the mtr */
1028
dulint end_lsn) /* in: end lsn of the mtr */
1061
byte type, /* in: log record type */
1062
ulint space, /* in: space id */
1063
ulint page_no, /* in: page number */
1064
byte* body, /* in: log record body */
1065
byte* rec_end, /* in: log record end */
1066
ib_uint64_t start_lsn, /* in: start lsn of the mtr */
1067
ib_uint64_t end_lsn) /* in: end lsn of the mtr */
1134
1173
Applies the hashed log records to the page, if the page lsn is less than the
1135
1174
lsn of a log record. This can be called when a buffer page has just been
1136
1175
read in, or also for a page already in the buffer pool. */
1139
1178
recv_recover_page(
1140
1179
/*==============*/
1141
ibool recover_backup, /* in: TRUE if we are recovering a backup
1180
ibool recover_backup,
1181
/* in: TRUE if we are recovering a backup
1142
1182
page: then we do not acquire any latches
1143
1183
since the page was read in outside the
1145
ibool just_read_in, /* in: TRUE if the i/o-handler calls this for
1186
/* in: TRUE if the i/o-handler calls this for
1146
1187
a freshly read page */
1147
page_t* page, /* in: buffer page */
1148
ulint space, /* in: space id */
1149
ulint page_no) /* in: page number */
1188
buf_block_t* block) /* in: buffer block */
1151
buf_block_t* block = NULL;
1152
1191
recv_addr_t* recv_addr;
1158
dulint page_newest_lsn;
1194
ib_uint64_t start_lsn;
1195
ib_uint64_t end_lsn;
1196
ib_uint64_t page_lsn;
1197
ib_uint64_t page_newest_lsn;
1159
1198
ibool modification_to_page;
1206
1247
rw_lock_x_lock_move_ownership(&(block->lock));
1209
success = buf_page_get_known_nowait(RW_X_LATCH, page,
1250
success = buf_page_get_known_nowait(RW_X_LATCH, block,
1211
1252
__FILE__, __LINE__,
1215
1256
#ifdef UNIV_SYNC_DEBUG
1216
buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
1257
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
1217
1258
#endif /* UNIV_SYNC_DEBUG */
1220
1261
/* Read the newest modification lsn from the page */
1221
page_lsn = mach_read_from_8(page + FIL_PAGE_LSN);
1262
page_lsn = mach_read_ull(page + FIL_PAGE_LSN);
1223
1264
if (!recover_backup) {
1224
1265
/* It may be that the page has been modified in the buffer
1225
1266
pool: read the newest modification lsn there */
1227
page_newest_lsn = buf_frame_get_newest_modification(page);
1269
= buf_page_get_newest_modification(&block->page);
1229
if (!ut_dulint_is_zero(page_newest_lsn)) {
1271
if (page_newest_lsn) {
1231
1273
page_lsn = page_newest_lsn;
1259
1301
if (recv->type == MLOG_INIT_FILE_PAGE) {
1260
1302
page_lsn = page_newest_lsn;
1262
mach_write_to_8(page + UNIV_PAGE_SIZE
1263
- FIL_PAGE_END_LSN_OLD_CHKSUM,
1265
mach_write_to_8(page + FIL_PAGE_LSN, ut_dulint_zero);
1304
mach_write_ull(page + UNIV_PAGE_SIZE
1305
- FIL_PAGE_END_LSN_OLD_CHKSUM, 0);
1306
mach_write_ull(page + FIL_PAGE_LSN, 0);
1268
if (ut_dulint_cmp(recv->start_lsn, page_lsn) >= 0) {
1309
if (recv->start_lsn >= page_lsn) {
1270
1311
if (!modification_to_page) {
1288
1329
recv_parse_or_apply_log_rec_body(recv->type, buf,
1289
1330
buf + recv->len,
1291
mach_write_to_8(page + UNIV_PAGE_SIZE
1292
- FIL_PAGE_END_LSN_OLD_CHKSUM,
1293
ut_dulint_add(recv->start_lsn,
1295
mach_write_to_8(page + FIL_PAGE_LSN,
1296
ut_dulint_add(recv->start_lsn,
1332
mach_write_ull(page + UNIV_PAGE_SIZE
1333
- FIL_PAGE_END_LSN_OLD_CHKSUM,
1334
recv->start_lsn + recv->len);
1335
mach_write_ull(page + FIL_PAGE_LSN,
1336
recv->start_lsn + recv->len);
1300
1339
if (recv->len > RECV_DATA_BLOCK_SIZE) {
1446
1484
mutex_exit(&(recv_sys->mutex));
1448
1486
if (buf_page_peek(space, page_no)) {
1450
1489
mtr_start(&mtr);
1452
page = buf_page_get(space, page_no,
1491
block = buf_page_get(
1492
space, zip_size, page_no,
1455
1494
#ifdef UNIV_SYNC_DEBUG
1456
buf_page_dbg_add_level(
1457
page, SYNC_NO_ORDER_CHECK);
1495
buf_block_dbg_add_level(
1496
block, SYNC_NO_ORDER_CHECK);
1458
1497
#endif /* UNIV_SYNC_DEBUG */
1459
recv_recover_page(FALSE, FALSE, page,
1498
recv_recover_page(FALSE, FALSE, block);
1461
1499
mtr_commit(&mtr);
1463
recv_read_in_area(space, page_no);
1501
recv_read_in_area(space, zip_size,
1466
1505
mutex_enter(&(recv_sys->mutex));
1529
1568
mutex_exit(&(recv_sys->mutex));
1571
#ifdef UNIV_HOTBACKUP
1572
/***********************************************************************
1573
Applies log records in the hash table to a backup. */
1576
recv_apply_log_recs_for_backup(void)
1577
/*================================*/
1579
recv_addr_t* recv_addr;
1587
recv_sys->apply_log_recs = TRUE;
1588
recv_sys->apply_batch_on = TRUE;
1590
block = buf_LRU_get_free_block(UNIV_PAGE_SIZE);
1592
fputs("InnoDB: Starting an apply batch of log records"
1593
" to the database...\n"
1594
"InnoDB: Progress in percents: ", stderr);
1596
n_hash_cells = hash_get_n_cells(recv_sys->addr_hash);
1598
for (i = 0; i < n_hash_cells; i++) {
1599
/* The address hash table is externally chained */
1600
recv_addr = hash_get_nth_cell(recv_sys->addr_hash, i)->node;
1602
while (recv_addr != NULL) {
1605
= fil_space_get_zip_size(recv_addr->space);
1607
if (zip_size == ULINT_UNDEFINED) {
1610
"InnoDB: Warning: cannot apply"
1612
" tablespace %lu page %lu,\n"
1613
"InnoDB: because tablespace with"
1614
" that id does not exist.\n",
1615
recv_addr->space, recv_addr->page_no);
1617
recv_addr->state = RECV_PROCESSED;
1619
ut_a(recv_sys->n_addrs);
1620
recv_sys->n_addrs--;
1622
goto skip_this_recv_addr;
1625
/* We simulate a page read made by the buffer pool, to
1626
make sure the recovery apparatus works ok. We must init
1629
buf_page_init_for_backup_restore(
1630
recv_addr->space, recv_addr->page_no,
1633
/* Extend the tablespace's last file if the page_no
1634
does not fall inside its bounds; we assume the last
1635
file is auto-extending, and ibbackup copied the file
1636
when it still was smaller */
1638
success = fil_extend_space_to_desired_size(
1640
recv_addr->space, recv_addr->page_no + 1);
1643
"InnoDB: Fatal error: cannot extend"
1644
" tablespace %lu to hold %lu pages\n",
1645
recv_addr->space, recv_addr->page_no);
1650
/* Read the page from the tablespace file using the
1651
fil0fil.c routines */
1654
error = fil_io(OS_FILE_READ, TRUE,
1655
recv_addr->space, zip_size,
1656
recv_addr->page_no, 0, zip_size,
1657
block->page.zip.data, NULL);
1659
error = fil_io(OS_FILE_READ, TRUE,
1660
recv_addr->space, 0,
1661
recv_addr->page_no, 0,
1663
block->frame, NULL);
1666
if (error != DB_SUCCESS) {
1668
"InnoDB: Fatal error: cannot read"
1670
" %lu page number %lu\n",
1671
(ulong) recv_addr->space,
1672
(ulong) recv_addr->page_no);
1677
/* Apply the log records to this page */
1678
recv_recover_page(TRUE, FALSE, block);
1680
/* Write the page back to the tablespace file using the
1681
fil0fil.c routines */
1683
buf_flush_init_for_writing(
1684
block->frame, buf_block_get_page_zip(block),
1685
mach_read_ull(block->frame + FIL_PAGE_LSN));
1688
error = fil_io(OS_FILE_WRITE, TRUE,
1689
recv_addr->space, zip_size,
1690
recv_addr->page_no, 0,
1692
block->page.zip.data, NULL);
1694
error = fil_io(OS_FILE_WRITE, TRUE,
1695
recv_addr->space, 0,
1696
recv_addr->page_no, 0,
1698
block->frame, NULL);
1700
skip_this_recv_addr:
1701
recv_addr = HASH_GET_NEXT(addr_hash, recv_addr);
1704
if ((100 * i) / n_hash_cells
1705
!= (100 * (i + 1)) / n_hash_cells) {
1706
fprintf(stderr, "%lu ",
1707
(ulong) ((100 * i) / n_hash_cells));
1712
buf_block_free(block);
1713
recv_sys_empty_hash();
1715
#endif /* UNIV_HOTBACKUP */
1533
1717
/***********************************************************************
1534
1718
Tries to parse a single log record and returns its length. */
1604
1788
/***********************************************************
1605
1789
Calculates the new value for lsn when more data is added to the log. */
1608
1792
recv_calc_lsn_on_data_add(
1609
1793
/*======================*/
1610
dulint lsn, /* in: old lsn */
1611
ulint len) /* in: this many bytes of data is added, log block
1612
headers not included */
1794
ib_uint64_t lsn, /* in: old lsn */
1795
ib_uint64_t len) /* in: this many bytes of data is
1796
added, log block headers not included */
1614
1798
ulint frag_len;
1617
frag_len = (ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
1801
frag_len = (((ulint) lsn) % OS_FILE_LOG_BLOCK_SIZE)
1618
1802
- LOG_BLOCK_HDR_SIZE;
1619
1803
ut_ad(frag_len < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE
1620
1804
- LOG_BLOCK_TRL_SIZE);
1621
lsn_len = len + ((len + frag_len)
1622
/ (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE
1623
- LOG_BLOCK_TRL_SIZE))
1805
lsn_len = (ulint) len;
1806
lsn_len += (lsn_len + frag_len)
1807
/ (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE
1808
- LOG_BLOCK_TRL_SIZE)
1624
1809
* (LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE);
1626
return(ut_dulint_add(lsn, lsn_len));
1811
return(lsn + lsn_len);
1814
#ifdef UNIV_LOG_DEBUG
1815
/***********************************************************
1816
Checks that the parser recognizes incomplete initial segments of a log
1817
record as incomplete. */
1820
recv_check_incomplete_log_recs(
1821
/*===========================*/
1822
byte* ptr, /* in: pointer to a complete log record */
1823
ulint len) /* in: length of the log record */
1831
for (i = 0; i < len; i++) {
1832
ut_a(0 == recv_parse_log_rec(ptr, ptr + i, &type, &space,
1836
#endif /* UNIV_LOG_DEBUG */
1629
1838
/***********************************************************
1630
1839
Prints diagnostic info of corrupt log. */
1640
1849
fprintf(stderr,
1641
1850
"InnoDB: ############### CORRUPT LOG RECORD FOUND\n"
1642
1851
"InnoDB: Log record type %lu, space id %lu, page number %lu\n"
1643
"InnoDB: Log parsing proceeded successfully up to %lu %lu\n"
1852
"InnoDB: Log parsing proceeded successfully up to %"PRIu64"\n"
1644
1853
"InnoDB: Previous log record type %lu, is multi %lu\n"
1645
1854
"InnoDB: Recv offset %lu, prev %lu\n",
1646
1855
(ulong) type, (ulong) space, (ulong) page_no,
1647
(ulong) ut_dulint_get_high(recv_sys->recovered_lsn),
1648
(ulong) ut_dulint_get_low(recv_sys->recovered_lsn),
1856
recv_sys->recovered_lsn,
1649
1857
(ulong) recv_previous_parsed_rec_type,
1650
1858
(ulong) recv_previous_parsed_rec_is_multi,
1651
1859
(ulong) (ptr - recv_sys->buf),
1774
1981
if (type == MLOG_DUMMY_RECORD) {
1775
1982
/* Do nothing */
1777
} else if (store_to_hash && (type == MLOG_FILE_CREATE
1778
|| type == MLOG_FILE_RENAME
1779
|| type == MLOG_FILE_DELETE)) {
1984
} else if (!store_to_hash) {
1985
/* In debug checking, update a replicate page
1986
according to the log record, and check that it
1987
becomes identical with the original page */
1988
#ifdef UNIV_LOG_DEBUG
1989
recv_check_incomplete_log_recs(ptr, len);
1990
#endif/* UNIV_LOG_DEBUG */
1992
} else if (type == MLOG_FILE_CREATE
1993
|| type == MLOG_FILE_CREATE2
1994
|| type == MLOG_FILE_RENAME
1995
|| type == MLOG_FILE_DELETE) {
1780
1997
#ifdef UNIV_HOTBACKUP
1781
1998
if (recv_replay_file_ops) {
1929
2140
recv_sys_add_to_parsing_buf(
1930
2141
/*========================*/
1931
/* out: TRUE if more data added */
1932
byte* log_block, /* in: log block */
1933
dulint scanned_lsn) /* in: lsn of how far we were able to find
1934
data in this log block */
2142
/* out: TRUE if more data added */
2143
byte* log_block, /* in: log block */
2144
ib_uint64_t scanned_lsn) /* in: lsn of how far we were able
2145
to find data in this log block */
1936
2147
ulint more_len;
1937
2148
ulint data_len;
1938
2149
ulint start_offset;
1939
2150
ulint end_offset;
1941
ut_ad(ut_dulint_cmp(scanned_lsn, recv_sys->scanned_lsn) >= 0);
2152
ut_ad(scanned_lsn >= recv_sys->scanned_lsn);
1943
if (ut_dulint_is_zero(recv_sys->parse_start_lsn)) {
2154
if (!recv_sys->parse_start_lsn) {
1944
2155
/* Cannot start parsing yet because no start point for
1950
2161
data_len = log_block_get_data_len(log_block);
1952
if (ut_dulint_cmp(recv_sys->parse_start_lsn, scanned_lsn) >= 0) {
1956
} else if (ut_dulint_cmp(recv_sys->scanned_lsn, scanned_lsn) >= 0) {
1960
} else if (ut_dulint_cmp(recv_sys->parse_start_lsn,
1961
recv_sys->scanned_lsn) > 0) {
1962
more_len = ut_dulint_minus(scanned_lsn,
1963
recv_sys->parse_start_lsn);
2163
if (recv_sys->parse_start_lsn >= scanned_lsn) {
2167
} else if (recv_sys->scanned_lsn >= scanned_lsn) {
2171
} else if (recv_sys->parse_start_lsn > recv_sys->scanned_lsn) {
2172
more_len = (ulint) (scanned_lsn - recv_sys->parse_start_lsn);
1965
more_len = ut_dulint_minus(scanned_lsn, recv_sys->scanned_lsn);
2174
more_len = (ulint) (scanned_lsn - recv_sys->scanned_lsn);
1968
2177
if (more_len == 0) {
2016
2225
/***********************************************************
2017
2226
Scans log from a buffer and stores new log data to the parsing buffer. Parses
2018
2227
and hashes the log records if new data found. */
2021
2230
recv_scan_log_recs(
2022
2231
/*===============*/
2023
/* out: TRUE if limit_lsn has been reached, or
2024
not able to scan any more in this log group */
2025
ibool apply_automatically,/* in: TRUE if we want this function to
2026
apply log records automatically when the
2027
hash table becomes full; in the hot backup tool
2028
the tool does the applying, not this
2030
ulint available_memory,/* in: we let the hash table of recs to grow
2031
to this size, at the maximum */
2032
ibool store_to_hash, /* in: TRUE if the records should be stored
2033
to the hash table; this is set to FALSE if just
2034
debug checking is needed */
2035
byte* buf, /* in: buffer containing a log segment or
2037
ulint len, /* in: buffer length */
2038
dulint start_lsn, /* in: buffer start lsn */
2039
dulint* contiguous_lsn, /* in/out: it is known that all log groups
2040
contain contiguous log data up to this lsn */
2041
dulint* group_scanned_lsn)/* out: scanning succeeded up to this lsn */
2232
/* out: TRUE if limit_lsn has been
2233
reached, or not able to scan any more
2234
in this log group */
2235
ibool apply_automatically,/* in: TRUE if we want this
2236
function to apply log records
2237
automatically when the hash table
2238
becomes full; in the hot backup tool
2239
the tool does the applying, not this
2241
ulint available_memory,/* in: we let the hash table of recs
2242
to grow to this size, at the maximum */
2243
ibool store_to_hash, /* in: TRUE if the records should be
2244
stored to the hash table; this is set
2245
to FALSE if just debug checking is
2247
byte* buf, /* in: buffer containing a log segment
2249
ulint len, /* in: buffer length */
2250
ib_uint64_t start_lsn, /* in: buffer start lsn */
2251
ib_uint64_t* contiguous_lsn, /* in/out: it is known that all log
2252
groups contain contiguous log data up
2254
ib_uint64_t* group_scanned_lsn)/* out: scanning succeeded up to
2259
ib_uint64_t scanned_lsn;
2050
ut_ad(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
2264
ut_ad(start_lsn % OS_FILE_LOG_BLOCK_SIZE == 0);
2051
2265
ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
2052
2266
ut_ad(len > 0);
2053
2267
ut_a(apply_automatically <= TRUE);
2137
if (ut_dulint_is_zero(recv_sys->parse_start_lsn)
2348
if (!recv_sys->parse_start_lsn
2138
2349
&& (log_block_get_first_rec_group(log_block) > 0)) {
2140
2351
/* We found a point from which to start the parsing
2141
2352
of log records */
2143
recv_sys->parse_start_lsn
2144
= ut_dulint_add(scanned_lsn,
2145
log_block_get_first_rec_group(
2354
recv_sys->parse_start_lsn = scanned_lsn
2355
+ log_block_get_first_rec_group(log_block);
2147
2356
recv_sys->scanned_lsn = recv_sys->parse_start_lsn;
2148
2357
recv_sys->recovered_lsn = recv_sys->parse_start_lsn;
2151
scanned_lsn = ut_dulint_add(scanned_lsn, data_len);
2360
scanned_lsn += data_len;
2153
if (ut_dulint_cmp(scanned_lsn, recv_sys->scanned_lsn) > 0) {
2362
if (scanned_lsn > recv_sys->scanned_lsn) {
2155
2364
/* We have found more entries. If this scan is
2156
2365
of startup type, we must initiate crash recovery
2253
2458
recv_group_scan_log_recs(
2254
2459
/*=====================*/
2255
log_group_t* group, /* in: log group */
2256
dulint* contiguous_lsn, /* in/out: it is known that all log groups
2257
contain contiguous log data up to this lsn */
2258
dulint* group_scanned_lsn)/* out: scanning succeeded up to this lsn */
2460
log_group_t* group, /* in: log group */
2461
ib_uint64_t* contiguous_lsn, /* in/out: it is known that all log
2462
groups contain contiguous log data up
2464
ib_uint64_t* group_scanned_lsn)/* out: scanning succeeded up to
2468
ib_uint64_t start_lsn;
2469
ib_uint64_t end_lsn;
2264
2471
finished = FALSE;
2266
2473
start_lsn = *contiguous_lsn;
2268
2475
while (!finished) {
2269
end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE);
2476
end_lsn = start_lsn + RECV_SCAN_SIZE;
2271
2478
log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
2272
2479
group, start_lsn, end_lsn);
2274
2481
finished = recv_scan_log_recs(
2275
TRUE, (buf_pool->n_frames - recv_n_pool_free_frames)
2482
TRUE, (buf_pool->curr_size - recv_n_pool_free_frames)
2276
2483
* UNIV_PAGE_SIZE, TRUE, log_sys->buf, RECV_SCAN_SIZE,
2277
2484
start_lsn, contiguous_lsn, group_scanned_lsn);
2278
2485
start_lsn = end_lsn;
2336
2542
to start processing of new user transactions, but the function
2337
2543
recv_recovery_from_checkpoint_finish should be called later to complete
2338
2544
the recovery and free the resources used in it. */
2341
2547
recv_recovery_from_checkpoint_start(
2342
2548
/*================================*/
2343
/* out: error code or DB_SUCCESS */
2344
ulint type, /* in: LOG_CHECKPOINT or LOG_ARCHIVE */
2345
dulint limit_lsn, /* in: recover up to this lsn if possible */
2346
dulint min_flushed_lsn,/* in: min flushed lsn from data files */
2347
dulint max_flushed_lsn)/* in: max flushed lsn from data files */
2549
/* out: error code or DB_SUCCESS */
2550
ulint type, /* in: LOG_CHECKPOINT or LOG_ARCHIVE */
2551
ib_uint64_t limit_lsn, /* in: recover up to this lsn
2553
ib_uint64_t min_flushed_lsn,/* in: min flushed lsn from
2555
ib_uint64_t max_flushed_lsn)/* in: max flushed lsn from
2349
2558
log_group_t* group;
2350
2559
log_group_t* max_cp_group;
2351
2560
log_group_t* up_to_date_group;
2352
2561
ulint max_cp_field;
2353
dulint checkpoint_lsn;
2354
dulint checkpoint_no;
2355
dulint old_scanned_lsn;
2356
dulint group_scanned_lsn;
2357
dulint contiguous_lsn;
2358
dulint archived_lsn;
2562
ib_uint64_t checkpoint_lsn;
2563
ib_uint64_t checkpoint_no;
2564
ib_uint64_t old_scanned_lsn;
2565
ib_uint64_t group_scanned_lsn;
2566
ib_uint64_t contiguous_lsn;
2567
ib_uint64_t archived_lsn;
2359
2568
ulint capacity;
2361
2570
byte log_hdr_buf[LOG_FILE_HDR_SIZE];
2364
ut_ad((type != LOG_CHECKPOINT)
2365
|| (ut_dulint_cmp(limit_lsn, ut_dulint_max) == 0));
2573
ut_ad(type != LOG_CHECKPOINT || limit_lsn == IB_ULONGLONG_MAX);
2367
2575
if (type == LOG_CHECKPOINT) {
2368
2576
recv_sys_create();
2400
2608
buf = log_sys->checkpoint_buf;
2402
checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
2403
checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
2404
archived_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN);
2610
checkpoint_lsn = mach_read_ull(buf + LOG_CHECKPOINT_LSN);
2611
checkpoint_no = mach_read_ull(buf + LOG_CHECKPOINT_NO);
2612
archived_lsn = mach_read_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN);
2406
2614
/* Read the first log file header to print a note if this is
2407
2615
a recovery from a restored InnoDB Hot Backup */
2409
fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, max_cp_group->space_id,
2617
fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, max_cp_group->space_id, 0,
2410
2618
0, 0, LOG_FILE_HDR_SIZE,
2411
2619
log_hdr_buf, max_cp_group);
2558
2762
" ib_logfiles to start up"
2559
2763
" the database?\n"
2560
2764
"InnoDB: Log sequence number in"
2561
" ib_logfiles is %lu %lu, log\n"
2765
" ib_logfiles is %"PRIu64", log\n"
2562
2766
"InnoDB: sequence numbers stamped"
2563
2767
" to ibdata file headers are between\n"
2564
"InnoDB: %lu %lu and %lu %lu.\n"
2768
"InnoDB: %"PRIu64" and %"PRIu64".\n"
2565
2769
"InnoDB: #########################"
2566
2770
"#################################\n",
2567
(ulong) ut_dulint_get_high(
2569
(ulong) ut_dulint_get_low(
2571
(ulong) ut_dulint_get_high(
2573
(ulong) ut_dulint_get_low(
2575
(ulong) ut_dulint_get_high(
2577
(ulong) ut_dulint_get_low(
2583
2776
if (!recv_needed_recovery) {
2599
2792
/* We currently have only one log group */
2600
if (ut_dulint_cmp(group_scanned_lsn, checkpoint_lsn) < 0) {
2793
if (group_scanned_lsn < checkpoint_lsn) {
2601
2794
ut_print_timestamp(stderr);
2602
2795
fprintf(stderr,
2603
2796
" InnoDB: ERROR: We were only able to scan the log"
2605
"InnoDB: %lu %lu, but a checkpoint was at %lu %lu.\n"
2798
"InnoDB: %"PRIu64", but a checkpoint was at %"PRIu64".\n"
2606
2799
"InnoDB: It is possible that"
2607
2800
" the database is now corrupt!\n",
2608
(ulong) ut_dulint_get_high(group_scanned_lsn),
2609
(ulong) ut_dulint_get_low(group_scanned_lsn),
2610
(ulong) ut_dulint_get_high(checkpoint_lsn),
2611
(ulong) ut_dulint_get_low(checkpoint_lsn));
2614
if (ut_dulint_cmp(group_scanned_lsn, recv_max_page_lsn) < 0) {
2805
if (group_scanned_lsn < recv_max_page_lsn) {
2615
2806
ut_print_timestamp(stderr);
2616
2807
fprintf(stderr,
2617
2808
" InnoDB: ERROR: We were only able to scan the log"
2619
"InnoDB: but a database page a had an lsn %lu %lu."
2809
" up to %"PRIu64"\n"
2810
"InnoDB: but a database page a had an lsn %"PRIu64"."
2620
2811
" It is possible that the\n"
2621
2812
"InnoDB: database is now corrupt!\n",
2622
(ulong) ut_dulint_get_high(group_scanned_lsn),
2623
(ulong) ut_dulint_get_low(group_scanned_lsn),
2624
(ulong) ut_dulint_get_high(recv_max_page_lsn),
2625
(ulong) ut_dulint_get_low(recv_max_page_lsn));
2628
if (ut_dulint_cmp(recv_sys->recovered_lsn, checkpoint_lsn) < 0) {
2817
if (recv_sys->recovered_lsn < checkpoint_lsn) {
2630
2819
mutex_exit(&(log_sys->mutex));
2632
if (ut_dulint_cmp(recv_sys->recovered_lsn, limit_lsn) >= 0) {
2821
if (recv_sys->recovered_lsn >= limit_lsn) {
2634
2823
return(DB_SUCCESS);
2664
2851
ut_memcpy(log_sys->buf, recv_sys->last_block, OS_FILE_LOG_BLOCK_SIZE);
2666
log_sys->buf_free = ut_dulint_get_low(log_sys->lsn)
2667
% OS_FILE_LOG_BLOCK_SIZE;
2853
log_sys->buf_free = (ulint) log_sys->lsn % OS_FILE_LOG_BLOCK_SIZE;
2668
2854
log_sys->buf_next_to_write = log_sys->buf_free;
2669
2855
log_sys->written_to_some_lsn = log_sys->lsn;
2670
2856
log_sys->written_to_all_lsn = log_sys->lsn;
2672
2858
log_sys->last_checkpoint_lsn = checkpoint_lsn;
2674
log_sys->next_checkpoint_no = ut_dulint_add(checkpoint_no, 1);
2860
log_sys->next_checkpoint_no = checkpoint_no + 1;
2676
2862
#ifdef UNIV_LOG_ARCHIVE
2677
if (ut_dulint_cmp(archived_lsn, ut_dulint_max) == 0) {
2863
if (archived_lsn == IB_ULONGLONG_MAX) {
2679
2865
log_sys->archiving_state = LOG_ARCH_OFF;
2761
2950
/* Rollback the uncommitted transactions which have no user
2764
os_thread_create(trx_rollback_or_clean_all_without_sess,
2953
os_thread_create(trx_rollback_or_clean_all_recovered,
2765
2954
(void *)&i, NULL);
2769
2958
/**********************************************************
2770
2959
Resets the logs. The contents of log files will be lost! */
2773
2962
recv_reset_logs(
2774
2963
/*============*/
2775
dulint lsn, /* in: reset to this lsn rounded up to
2776
be divisible by OS_FILE_LOG_BLOCK_SIZE,
2777
after which we add LOG_BLOCK_HDR_SIZE */
2964
ib_uint64_t lsn, /* in: reset to this lsn
2965
rounded up to be divisible by
2966
OS_FILE_LOG_BLOCK_SIZE, after
2968
LOG_BLOCK_HDR_SIZE */
2778
2969
#ifdef UNIV_LOG_ARCHIVE
2779
ulint arch_log_no, /* in: next archived log file number */
2970
ulint arch_log_no, /* in: next archived log file number */
2780
2971
#endif /* UNIV_LOG_ARCHIVE */
2781
ibool new_logs_created)/* in: TRUE if resetting logs is done
2782
at the log creation; FALSE if it is done
2783
after archive recovery */
2972
ibool new_logs_created)/* in: TRUE if resetting logs
2973
is done at the log creation;
2974
FALSE if it is done after
2785
2977
log_group_t* group;
2787
2979
ut_ad(mutex_own(&(log_sys->mutex)));
2789
log_sys->lsn = ut_dulint_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE);
2981
log_sys->lsn = ut_uint64_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE);
2791
2983
group = UT_LIST_GET_FIRST(log_sys->log_groups);
2821
3013
log_block_set_first_rec_group(log_sys->buf, LOG_BLOCK_HDR_SIZE);
2823
3015
log_sys->buf_free = LOG_BLOCK_HDR_SIZE;
2824
log_sys->lsn = ut_dulint_add(log_sys->lsn, LOG_BLOCK_HDR_SIZE);
3016
log_sys->lsn += LOG_BLOCK_HDR_SIZE;
2826
3018
mutex_exit(&(log_sys->mutex));
2828
3020
/* Reset the checkpoint fields in logs */
2830
log_make_checkpoint_at(ut_dulint_max, TRUE);
2831
log_make_checkpoint_at(ut_dulint_max, TRUE);
3022
log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);
3023
log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);
2833
3025
mutex_enter(&(log_sys->mutex));
3121
3312
/************************************************************
3122
3313
Recovers from archived log files, and also from log files, if they exist. */
3125
3316
recv_recovery_from_archive_start(
3126
3317
/*=============================*/
3127
/* out: error code or DB_SUCCESS */
3128
dulint min_flushed_lsn,/* in: min flushed lsn field from the
3130
dulint limit_lsn, /* in: recover up to this lsn if possible */
3131
ulint first_log_no) /* in: number of the first archived log file
3132
to use in the recovery; the file will be
3133
searched from INNOBASE_LOG_ARCH_DIR specified
3134
in server config file */
3318
/* out: error code or DB_SUCCESS */
3319
ib_uint64_t min_flushed_lsn,/* in: min flushed lsn field from the
3321
ib_uint64_t limit_lsn, /* in: recover up to this lsn if
3323
ulint first_log_no) /* in: number of the first archived
3324
log file to use in the recovery; the
3325
file will be searched from
3326
INNOBASE_LOG_ARCH_DIR specified in
3327
server config file */
3136
3329
log_group_t* group;
3137
3330
ulint group_id;