Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-25979

Invalid undo page number written to DB_ROLL_PTR

    XMLWordPrintable

    Details

      Description

      MDEV-15090 introduced a race condition in trx_undo_report_row_operation() that would be fixed by the following:

      diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc
      index 9c7106facaf..e011b3f5d8e 100644
      --- a/storage/innobase/trx/trx0rec.cc
      +++ b/storage/innobase/trx/trx0rec.cc
      @@ -2054,12 +2054,11 @@ trx_undo_report_row_operation(
       				goto err_exit;
       			}
       
      -			mtr_commit(&mtr);
      +			mtr.commit();
       		} else {
       			/* Success */
      -			mtr_commit(&mtr);
      -
       			undo->top_page_no = undo_block->page.id.page_no();
      +			mtr.commit();
       			undo->top_offset  = offset;
       			undo->top_undo_no = trx->undo_no++;
       			undo->guess_block = undo_block;
      

      This could cause various types of failure. In the trace that I analyzed most recently, the page had been evicted from the buffer pool by the LRU mechanism but not yet replaced with another page. Thus, the undo->top_page_no had been assigned to FIL_NULL, triggering an error message later when the DB_ROLL_PTR column in a B-tree record was dereferenced:

      2021-06-17  7:10:52 17 [ERROR] [FATAL] InnoDB: Trying to read 4096 bytes at 17592186040320 outside the bounds of the file: .//undo001
      

      Note: the reported byte offset is 4096*0xffffffff.

      In another trace that I started analyzing earlier (with innodb_file_per_table=0 and no separate undo tablespaces), the error was something different. I suspect that the page had not only been evicted but the block descriptor started to point to a B-tree page. Thus, the DB_ROLL_PTR would wrongly point to a B-tree page instead of the undo log page that had just been written. Ultimately, an assertion failure would be triggered for attempting to interpret some bytes in the middle of a B-tree page as an undo log record.

      I think that it should be relatively hard to hit this bug in practice. It would likely require using an extremely small buffer pool, so that page eviction or replacement could take place between those 2 statements.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              marko Marko Mäkelä
              Reporter:
              marko Marko Mäkelä
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Git Integration