diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index fb212e1..66501d3 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -430,6 +430,18 @@ class MetadataRecover { const bool read_only; }; +/** Avoid second parsing of multi-record log entry*/ +struct MultiContent { + mlog_id_t type; + ulint len; + byte *body; + byte *rec_end; + space_id_t space_id; + page_no_t page_no; +}; + +#define MAX_MULTI_CONTENT_ARRAY_SIZE 8192 + /** Recovery system data structure */ struct recv_sys_t { using Pages = @@ -598,6 +610,8 @@ struct recv_sys_t { /** Tablespace IDs that were explicitly deleted. */ Missing_Ids deleted; + + MultiContent multi_recs[MAX_MULTI_CONTENT_ARRAY_SIZE]; }; /** The recovery system */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index e03270f..712e6b4 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2939,6 +2939,16 @@ static bool recv_multi_rec(byte *ptr, byte *end_ptr) { return (true); } + if (n_recs < MAX_MULTI_CONTENT_ARRAY_SIZE) { + MultiContent *rec = &(recv_sys->multi_recs[n_recs]); + rec->type = type; + rec->len = len; + rec->body = body; + rec->rec_end = ptr + len; + rec->space_id = space_id; + rec->page_no = page_no; + } + recv_previous_parsed_rec_type = type; recv_previous_parsed_rec_offset = recv_sys->recovered_offset + total_len; @@ -2978,18 +2988,32 @@ static bool recv_multi_rec(byte *ptr, byte *end_ptr) { ptr = recv_sys->buf + recv_sys->recovered_offset; - for (;;) { + for (ulint i = 0; i < n_recs; i++) { lsn_t old_lsn = recv_sys->recovered_lsn; /* This will apply MLOG_FILE_ records. */ mlog_id_t type = MLOG_BIGGEST_TYPE; byte *body; + byte *rec_end; page_no_t page_no = 0; space_id_t space_id = 0; + ulint len; - ulint len = recv_parse_log_rec(&type, ptr, end_ptr, &space_id, &page_no, - false, &body); + if (i < MAX_MULTI_CONTENT_ARRAY_SIZE) { + /* This will apply MLOG_FILE_ records. */ + MultiContent* rec = &(recv_sys->multi_recs[i]); + type = rec->type; + body = rec->body; + rec_end = rec->rec_end; + page_no = rec->page_no; + space_id = rec->space_id; + len = rec->len; + ut_ad(rec_end == ptr + len); + } else { + len = recv_parse_log_rec(&type, ptr, end_ptr, &space_id, &page_no, &body); + rec_end = ptr + len; + } if (recv_sys->found_corrupt_log && !recv_report_corrupt_log(ptr, type, space_id, page_no)) { @@ -3044,7 +3068,7 @@ static bool recv_multi_rec(byte *ptr, byte *end_ptr) { fil_tablespace_lookup_for_recovery(space_id)) { #endif /* !UNIV_HOTBACKUP */ - recv_add_to_hash_table(type, space_id, page_no, body, ptr + len, + recv_add_to_hash_table(type, space_id, page_no, body, rec_end, old_lsn, new_recovered_lsn); #ifndef UNIV_HOTBACKUP