• Marko Mäkelä's avatar
    MDEV-23190 InnoDB data file extension is not crash-safe · 57ec42bc
    Marko Mäkelä authored
    When InnoDB is extending a data file, it is updating the FSP_SIZE
    field in the first page of the data file.
    
    In commit 8451e090 (MDEV-11556)
    we removed a work-around for this bug and made recovery stricter,
    by making it track changes to FSP_SIZE via redo log records, and
    extend the data files before any changes are being applied to them.
    
    It turns out that the function fsp_fill_free_list() is not crash-safe
    with respect to this when it is initializing the change buffer bitmap
    page (page 1, or generally, N*innodb_page_size+1). It uses a separate
    mini-transaction that is committed (and will be written to the redo
    log file) before the mini-transaction that actually extended the data
    file. Hence, recovery can observe a reference to a page that is
    beyond the current end of the data file.
    
    fsp_fill_free_list(): Initialize the change buffer bitmap page in
    the same mini-transaction.
    
    The rest of the changes are fixing a bug that the use of the separate
    mini-transaction was attempting to work around. Namely, we must ensure
    that no other thread will access the change buffer bitmap page before
    our mini-transaction has been committed and all page latches have been
    released.
    
    That is, for read-ahead as well as neighbour flushing, we must avoid
    accessing pages that might not yet be durably part of the tablespace.
    
    fil_space_t::committed_size: The size of the tablespace
    as persisted by mtr_commit().
    
    fil_space_t::max_page_number_for_io(): Limit the highest page
    number for I/O batches to committed_size.
    
    MTR_MEMO_SPACE_X_LOCK: Replaces MTR_MEMO_X_LOCK for fil_space_t::latch.
    
    mtr_x_space_lock(): Replaces mtr_x_lock() for fil_space_t::latch.
    
    mtr_memo_slot_release_func(): When releasing MTR_MEMO_SPACE_X_LOCK,
    copy space->size to space->committed_size. In this way, read-ahead
    or flushing will never be invoked on pages that do not yet exist
    according to FSP_SIZE.
    57ec42bc
fsp0fsp.cc 116 KB