Bug #106238 Wrong FIL_PAGE_LSN set during crash recovery
Submitted: 21 Jan 2022 16:59 Modified: 24 Jan 2022 14:11
Reporter: Kang Wang Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S2 (Serious)
Version:All OS:Any
Assigned to: CPU Architecture:Any

[21 Jan 2022 16:59] Kang Wang
Description:
After one redo record apply up on some page during Crash Recovery, FIL_PAGE_LSN will be update as the end_lsn of that record.

But it is a miscalculation in recv_recover_page_func:

<=======
      recv_parse_or_apply_log_rec_body(recv->type, buf, buf + recv->len,
                                       recv_addr->space, recv_addr->page_no,
                                       block, &mtr, ULINT_UNDEFINED);

      end_lsn = recv->start_lsn + recv->len;

      mach_write_to_8(FIL_PAGE_LSN + page, end_lsn);

      mach_write_to_8(UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + page,
                      end_lsn);

========>

The end_lsn should be recv->end_lsn rather than recv->start_lsn + recv->len.

Since recv->len is Log record body length in bytes, it is meaningless to add to recv->start_lsn.

How to repeat:
By Read Code

Suggested fix:
Just remove the local end_lsn and use the one outside.

<=======
-      lsn_t end_lsn;
-
       if (!modification_to_page) {
 #ifndef UNIV_HOTBACKUP
         ut_a(recv_needed_recovery);
@@ -2609,8 +2607,6 @@ void recv_recover_page_func(
                                        recv_addr->space, recv_addr->page_no,
                                        block, &mtr, ULINT_UNDEFINED);

-      end_lsn = recv->start_lsn + recv->len;
-
       mach_write_to_8(FIL_PAGE_LSN + page, end_lsn);

       mach_write_to_8(UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + page,
========>
[24 Jan 2022 13:53] MySQL Verification Team
Hi Mr. Wang,

Thank you for your bug report.

However, we do need the exact release of 8.0 in which this error occurs. Also, what are the consequences of this error ????

Last but not least, is there any way that we can reproduce this problem.
[24 Jan 2022 14:11] MySQL Verification Team
Hi Mr. Wang,

This is also to inform you that in the latest release of 8.0, there is no more local end_lsn.

There is an end_lsn in a separate block, which does not apply to the block that you are referring to:

   if (recv->start_lsn >= page_lsn ) {

      lsn_t end_lsn;

      if (!modification_to_page) {
        modification_to_page = true;
        start_lsn = recv->start_lsn;
    }

Hence, the above end_lsn does not apply to the code below it, where the end_lsn from the upper block is the only one that is used.

Hence, this is not a bug.