📄 log0recv.c
字号:
+ LOG_CHECKPOINT_CHECKSUM_1)); }#endif /* UNIV_DEBUG */ goto not_consistent; } group->state = LOG_GROUP_OK; group->lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); group->lsn_offset = mach_read_from_4(buf + LOG_CHECKPOINT_OFFSET); checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO);#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "InnoDB: Checkpoint number %lu found in group %lu\n", (ulong) ut_dulint_get_low(checkpoint_no), (ulong) group->id); }#endif /* UNIV_DEBUG */ if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) { *max_group = group; *max_field = field; max_no = checkpoint_no; } not_consistent: ; } group = UT_LIST_GET_NEXT(log_groups, group); } if (*max_group == NULL) { fprintf(stderr,"InnoDB: No valid checkpoint found.\n""InnoDB: If this error appears when you are creating an InnoDB database,\n""InnoDB: the problem may be that during an earlier attempt you managed\n""InnoDB: to create the InnoDB data files, but log file creation failed.\n""InnoDB: If that is the case, please refer to\n""InnoDB: http://dev.mysql.com/doc/mysql/en/Error_creating_InnoDB.html\n"); return(DB_ERROR); } return(DB_SUCCESS);}/***********************************************************************Reads the checkpoint info needed in hot backup. */iboolrecv_read_cp_info_for_backup(/*=========================*/ /* out: TRUE if success */ byte* hdr, /* in: buffer containing the log group header */ dulint* lsn, /* out: checkpoint lsn */ ulint* offset, /* out: checkpoint offset in the log group */ ulint* fsp_limit,/* out: fsp limit of space 0, 1000000000 if the database is running with < version 3.23.50 of InnoDB */ dulint* cp_no, /* out: checkpoint number */ dulint* first_header_lsn) /* out: lsn of of the start of the first log file */{ ulint max_cp = 0; dulint max_cp_no = ut_dulint_zero; byte* cp_buf; cp_buf = hdr + LOG_CHECKPOINT_1; if (recv_check_cp_is_consistent(cp_buf)) { max_cp_no = mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO); max_cp = LOG_CHECKPOINT_1; } cp_buf = hdr + LOG_CHECKPOINT_2; if (recv_check_cp_is_consistent(cp_buf)) { if (ut_dulint_cmp(mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO), max_cp_no) > 0) { max_cp = LOG_CHECKPOINT_2; } } if (max_cp == 0) { return(FALSE); } cp_buf = hdr + max_cp; *lsn = mach_read_from_8(cp_buf + LOG_CHECKPOINT_LSN); *offset = mach_read_from_4(cp_buf + LOG_CHECKPOINT_OFFSET); /* If the user is running a pre-3.23.50 version of InnoDB, its checkpoint data does not contain the fsp limit info */ if (mach_read_from_4(cp_buf + LOG_CHECKPOINT_FSP_MAGIC_N) == LOG_CHECKPOINT_FSP_MAGIC_N_VAL) { *fsp_limit = mach_read_from_4( cp_buf + LOG_CHECKPOINT_FSP_FREE_LIMIT); if (*fsp_limit == 0) { *fsp_limit = 1000000000; } } else { *fsp_limit = 1000000000; }/* fprintf(stderr, "fsp limit %lu MB\n", *fsp_limit); */ *cp_no = mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO); *first_header_lsn = mach_read_from_8(hdr + LOG_FILE_START_LSN); return(TRUE);}/**********************************************************Checks the 4-byte checksum to the trailer checksum field of a log block.We also accept a log block in the old format < InnoDB-3.23.52 where thechecksum field contains the log block number. */staticiboollog_block_checksum_is_ok_or_old_format(/*===================================*/ /* out: TRUE if ok, or if the log block may be in the format of InnoDB version < 3.23.52 */ byte* block) /* in: pointer to a log block */{#ifdef UNIV_LOG_DEBUG return(TRUE);#endif /* UNIV_LOG_DEBUG */ if (log_block_calc_checksum(block) == log_block_get_checksum(block)) { return(TRUE); } if (log_block_get_hdr_no(block) == log_block_get_checksum(block)) { /* We assume the log block is in the format of InnoDB version < 3.23.52 and the block is ok *//* fprintf(stderr,"InnoDB: Scanned old format < InnoDB-3.23.52 log block number %lu\n", log_block_get_hdr_no(block));*/ return(TRUE); } return(FALSE);}/***********************************************************************Scans the log segment and n_bytes_scanned is set to the length of validlog scanned. */voidrecv_scan_log_seg_for_backup(/*=========================*/ byte* buf, /* in: buffer containing log data */ ulint buf_len, /* in: data length in that buffer */ dulint* scanned_lsn, /* in/out: lsn of buffer start, we return scanned lsn */ ulint* scanned_checkpoint_no, /* in/out: 4 lowest bytes of the highest scanned checkpoint number so far */ ulint* n_bytes_scanned)/* out: how much we were able to scan, smaller than buf_len if log data ended here */{ ulint data_len; byte* log_block; ulint no; *n_bytes_scanned = 0; for (log_block = buf; log_block < buf + buf_len; log_block += OS_FILE_LOG_BLOCK_SIZE) { no = log_block_get_hdr_no(log_block);/* fprintf(stderr, "Log block header no %lu\n", no); */ if (no != log_block_convert_lsn_to_no(*scanned_lsn) || !log_block_checksum_is_ok_or_old_format(log_block)) {/* fprintf(stderr,"Log block n:o %lu, scanned lsn n:o %lu\n", no, log_block_convert_lsn_to_no(*scanned_lsn));*/ /* Garbage or an incompletely written log block */ log_block += OS_FILE_LOG_BLOCK_SIZE;/* fprintf(stderr,"Next log block n:o %lu\n", log_block_get_hdr_no(log_block));*/ break; } if (*scanned_checkpoint_no > 0 && log_block_get_checkpoint_no(log_block) < *scanned_checkpoint_no && *scanned_checkpoint_no - log_block_get_checkpoint_no(log_block) > 0x80000000UL) { /* Garbage from a log buffer flush which was made before the most recent database recovery *//* fprintf(stderr, "Scanned cp n:o %lu, block cp n:o %lu\n", *scanned_checkpoint_no, log_block_get_checkpoint_no(log_block));*/ break; } data_len = log_block_get_data_len(log_block); *scanned_checkpoint_no = log_block_get_checkpoint_no(log_block); *scanned_lsn = ut_dulint_add(*scanned_lsn, data_len); *n_bytes_scanned += data_len; if (data_len < OS_FILE_LOG_BLOCK_SIZE) { /* Log data ends here */ /* fprintf(stderr, "Log block data len %lu\n", data_len); */ break; } }}/***********************************************************************Tries to parse a single log record body and also applies it to a page ifspecified. File ops are parsed, but not applied in this function. */staticbyte*recv_parse_or_apply_log_rec_body(/*=============================*/ /* out: log record end, NULL if not a complete record */ byte type, /* in: type */ byte* ptr, /* in: pointer to a buffer */ byte* end_ptr,/* in: pointer to the buffer end */ page_t* page, /* in: buffer page or NULL; if not NULL, then the log record is applied to the page, and the log record should be complete then */ mtr_t* mtr) /* in: mtr or NULL; should be non-NULL if and only if page is non-NULL */{ dict_index_t* index = NULL; switch (type) { case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES: ptr = mlog_parse_nbytes(type, ptr, end_ptr, page); break; case MLOG_REC_INSERT: case MLOG_COMP_REC_INSERT: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_INSERT, &index))) { ut_a(!page || (ibool)!!page_is_comp(page)==index->table->comp); ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr, index, page, mtr); } break; case MLOG_REC_CLUST_DELETE_MARK: case MLOG_COMP_REC_CLUST_DELETE_MARK: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_CLUST_DELETE_MARK, &index))) { ut_a(!page || (ibool)!!page_is_comp(page)==index->table->comp); ptr = btr_cur_parse_del_mark_set_clust_rec(ptr, end_ptr, index, page); } break; case MLOG_COMP_REC_SEC_DELETE_MARK: /* This log record type is obsolete, but we process it for backward compatibility with MySQL 5.0.3 and 5.0.4. */ ut_a(!page || page_is_comp(page)); ptr = mlog_parse_index(ptr, end_ptr, TRUE, &index); if (!ptr) { break; } /* Fall through */ case MLOG_REC_SEC_DELETE_MARK: ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr, page); break; case MLOG_REC_UPDATE_IN_PLACE: case MLOG_COMP_REC_UPDATE_IN_PLACE: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_UPDATE_IN_PLACE, &index))) { ut_a(!page || (ibool)!!page_is_comp(page)==index->table->comp); ptr = btr_cur_parse_update_in_place(ptr, end_ptr, page, index); } break; case MLOG_LIST_END_DELETE: case MLOG_COMP_LIST_END_DELETE: case MLOG_LIST_START_DELETE: case MLOG_COMP_LIST_START_DELETE: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_LIST_END_DELETE || type == MLOG_COMP_LIST_START_DELETE, &index))) { ut_a(!page || (ibool)!!page_is_comp(page)==index->table->comp); ptr = page_parse_delete_rec_list(type, ptr, end_ptr, index, page, mtr); } break; case MLOG_LIST_END_COPY_CREATED: case MLOG_COMP_LIST_END_COPY_CREATED: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_LIST_END_COPY_CREATED, &index))) { ut_a(!page || (ibool)!!page_is_comp(page)==index->table->comp); ptr = page_parse_copy_rec_list_to_created_page(ptr, end_ptr, index, page, mtr); } break; case MLOG_PAGE_REORGANIZE: case MLOG_COMP_PAGE_REORGANIZE: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_PAGE_REORGANIZE, &index))) { ut_a(!page || (ibool)!!page_is_comp(page)==index->table->comp); ptr = btr_parse_page_reorganize(ptr, end_ptr, index, page, mtr); } break; case MLOG_PAGE_CREATE: case MLOG_COMP_PAGE_CREATE: ptr = page_parse_create(ptr, end_ptr, type == MLOG_COMP_PAGE_CREATE, page, mtr); break; case MLOG_UNDO_INSERT: ptr = trx_undo_parse_add_undo_rec(ptr, end_ptr, page); break; case MLOG_UNDO_ERASE_END: ptr = trx_undo_parse_erase_page_end(ptr, end_ptr, page, mtr); break; case MLOG_UNDO_INIT: ptr = trx_undo_parse_page_init(ptr, end_ptr, page, mtr); break; case MLOG_UNDO_HDR_DISCARD: ptr = trx_undo_parse_discard_latest(ptr, end_ptr, page, mtr); break; case MLOG_UNDO_HDR_CREATE: case MLOG_UNDO_HDR_REUSE: ptr = trx_undo_parse_page_header(type, ptr, end_ptr, page, mtr); break; case MLOG_REC_MIN_MARK: case MLOG_COMP_REC_MIN_MARK: ptr = btr_parse_set_min_rec_mark(ptr, end_ptr, type == MLOG_COMP_REC_MIN_MARK, page, mtr); break; case MLOG_REC_DELETE: case MLOG_COMP_REC_DELETE: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_DELETE, &index))) { ut_a(!page || (ibool)!!page_is_comp(page)==index->table->comp); ptr = page_cur_parse_delete_rec(ptr, end_ptr, index, page, mtr); } break; case MLOG_IBUF_BITMAP_INIT: ptr = ibuf_parse_bitmap_init(ptr, end_ptr, page, mtr); break; case MLOG_INIT_FILE_PAGE: ptr = fsp_parse_init_file_page(ptr, end_ptr, page); break; case MLOG_WRITE_STRING: ptr = mlog_parse_string(ptr, end_ptr, page); break; case MLOG_FILE_CREATE: case MLOG_FILE_RENAME: case MLOG_FILE_DELETE: ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE, ULINT_UNDEFINED); break; default: ptr = NULL; recv_sys->found_corrupt_log = TRUE; } ut_ad(!page || ptr); if (index) { dict_table_t* table = index->table; mem_heap_free(index->heap); mutex_free(&(table->autoinc_mutex)); mem_heap_free(table->heap); } return(ptr);}/*************************************************************************Calculates the fold value of a page file address: used in inserting orsearching for a log record in the hash table. */UNIV_INLINEulintrecv_fold(/*======*/ /* out: folded value */ ulint space, /* in: space */ ulint page_no)/* in: page number */{ return(ut_fold_ulint_pair(space, page_no));}/*************************************************************************Calculates the hash value of a page file address: used in inserting orsearching for a log record in the hash table. */UNIV_INLINEulintrecv_hash(/*======*/ /* out: folded value */ ulint space, /* in: space */ ulint page_no)/* in: page number */{ return(hash_calc_hash(recv_fold(space, page_no), recv_sys->addr_hash));}/*************************************************************************Gets the hashed file address struct for a page. */staticrecv_addr_t*recv_get_fil_addr_struct(/*=====================*/ /* out: file address struct, NULL if not found from the hash table */ ulint space, /* in: space id */ ulint page_no)/* in: page number */{ recv_addr_t* recv_addr; recv_addr = HASH_GET_FIRST(recv_sys->addr_hash, recv_hash(space, page_no)); while (recv_addr) { if ((recv_addr->space == space) && (recv_addr->page_no == page_no)) { break; } recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); } return(recv_addr);}/***********************************************************************Adds a new log record to the hash table of log records. */staticvoidrecv_add_to_hash_table(/*===================*/ byte type, /* in: log record type */ ulint space, /* in: space id */ ulint page_no, /* in: page number */ byte* body, /* in: log record body */ byte* rec_end, /* in: log record end */ dulint start_lsn, /* in: start lsn of the mtr */ dulint end_lsn) /* in: end lsn of the mtr */{ recv_t* recv; ulint len; recv_data_t* recv_data; recv_data_t** prev_field; recv_addr_t* recv_addr; if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { /* The tablespace does not exist any more: do not store the log record */ return; } len = rec_end - body; recv = mem_heap_alloc(recv_sys->heap, sizeof(recv_t)); recv->type = type; recv->len = rec_end - body; recv->start_lsn = start_lsn; recv->end_lsn = end_lsn; recv_addr = recv_get_fil_addr_struct(space, page_no); if (recv_addr == NULL) { recv_addr = mem_heap_alloc(recv_sys->heap, sizeof(recv_addr_t)); recv_addr->space = space; recv_addr->page_no = page_no;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -