• Marko Mäkelä's avatar
    MDEV-29911 InnoDB recovery and mariadb-backup --prepare fail to report detailed progress · f2c17cc9
    Marko Mäkelä authored
    This is a 10.6 port of commit 2f9e2647
    from MariaDB Server 10.9 that is missing some optimization due to a
    more complex redo log format and recovery logic
    (which was simplified in commit 685d958e).
    
    The progress reporting of InnoDB crash recovery was rather intermittent.
    Nothing was reported during the single-threaded log record parsing, which
    could consume minutes when parsing a large log. During log application,
    there only was progress reporting in background threads that would be
    invoked on data page read completion.
    
    The progress reporting here will be detailed like this:
    
    InnoDB: Starting crash recovery from checkpoint LSN=628599973,5653727799
    InnoDB: Read redo log up to LSN=1963895808
    InnoDB: Multi-batch recovery needed at LSN 2534560930
    InnoDB: Read redo log up to LSN=3312233472
    InnoDB: Read redo log up to LSN=1599646720
    InnoDB: Read redo log up to LSN=2160831488
    InnoDB: To recover: LSN 2806789376/2806819840; 195082 pages
    InnoDB: To recover: LSN 2806789376/2806819840; 63507 pages
    InnoDB: Read redo log up to LSN=3195776000
    InnoDB: Read redo log up to LSN=3687099392
    InnoDB: Read redo log up to LSN=4165315584
    InnoDB: To recover: LSN 4374395699/4374440960; 241454 pages
    InnoDB: To recover: LSN 4374395699/4374440960; 123701 pages
    InnoDB: Read redo log up to LSN=4508724224
    InnoDB: Read redo log up to LSN=5094550528
    InnoDB: To recover: 205230 pages
    
    The previous messages "Starting a batch to recover" or
    "Starting a final batch to recover" will be replaced by
    "To recover: ... pages" messages.
    
    If a batch lasts longer than 15 seconds, then there will be
    progress reports every 15 seconds, showing the number of remaining pages.
    For the non-final batch, the "To recover:" message includes two end LSN:
    that of the batch, and of the recovered log. This is the primary measure
    of progress. The batch will end once the number of pages to recover
    reaches 0.
    
    If recovery is possible in a single batch, the output will look like this,
    with a shorter "To recover:" message that counts only the remaining pages:
    
    InnoDB: Starting crash recovery from checkpoint LSN=628599973,5653727799
    InnoDB: Read redo log up to LSN=1984539648
    InnoDB: Read redo log up to LSN=2710875136
    InnoDB: Read redo log up to LSN=3358895104
    InnoDB: Read redo log up to LSN=3965299712
    InnoDB: Read redo log up to LSN=4557417472
    InnoDB: Read redo log up to LSN=5219527680
    InnoDB: To recover: 450915 pages
    
    We will also speed up recovery by improving the memory management and
    implementing multi-threaded recovery of data pages that will not need
    to be read into the buffer pool ("fake read"). Log application in the
    "fake read" threads will be protected by an atomic being_recovered field
    and exclusive buf_page_t::lock.
    
    Recovery will reserve for data pages two thirds of the buffer pool,
    or 256 pages, whichever is smaller. Previously, we could only use at most
    one third of the buffer pool for buffered log records. This would typically
    mean that with large buffer pools, recovery unnecessary consisted of
    multiple batches.
    
    If recovery runs out of memory, it will "roll back" or "rewind" the current
    mini-transaction. The recv_sys.recovered_lsn and recv_sys.pages
    will correspond to the "out of memory LSN", at the end of the previous
    complete mini-transaction.
    
    If recovery runs out of memory while executing the final recovery batch,
    we can simply invoke recv_sys.apply(false) to make room, and resume
    parsing.
    
    If recovery runs out of memory before the final batch, we will
    scan the redo log to the end and check for any missing or inconsistent
    files. In this version of the patch, we will throw away any previously
    buffered recv_sys.pages and rescan the log from the checkpoint onwards.
    
    recv_sys_t::pages_it: A cached iterator to recv_sys.pages.
    
    recv_sys_t::is_memory_exhausted(): Remove. We will have out-of-memory
    handling deep inside recv_sys_t::parse().
    
    recv_sys_t::rewind(), page_recv_t::recs_t::rewind():
    Remove all log starting with a specific LSN.
    
    IORequest::write_complete(), IORequest::read_complete():
    Replaces fil_aio_callback().
    
    read_io_callback(), write_io_callback(): Replaces io_callback().
    
    IORequest::fake_read_complete(), fake_io_callback(), os_fake_read():
    Process a "fake read" request for concurrent recovery.
    
    recv_sys_t::apply_batch(): Choose a number of successive pages
    for a recovery batch.
    
    recv_sys_t::erase(recv_sys_t::map::iterator): Remove log records for a
    page whose recovery is not in progress. Log application threads
    will not invoke this; they will only set being_recovered=-1 to indicate
    that the entry is no longer needed.
    
    recv_sys_t::garbage_collect(): Remove all being_recovered=-1 entries.
    
    recv_sys_t::wait_for_pool(): Wait for some space to become available
    in the buffer pool.
    
    mlog_init_t::mark_ibuf_exist(): Avoid calls to
    recv_sys::recover_low() via ibuf_page_exists() and buf_page_get_low().
    Such calls would lead to double locking of recv_sys.mutex, which
    depending on implementation could cause a deadlock. We will use
    lower-level calls to look up index pages.
    
    buf_LRU_block_remove_hashed(): Disable consistency checks for freed
    ROW_FORMAT=COMPRESSED pages. Their contents could be uninitialized garbage.
    This fixes an occasional failure of the test
    innodb.innodb_bulk_create_index_debug.
    
    Tested by: Matthias Leich
    f2c17cc9
os0file.cc 101 KB