• Marko Mäkelä's avatar
    MDEV-21347 innodb_log_optimize_ddl=OFF is not crash safe · 147d4b1e
    Marko Mäkelä authored
    In commit 0f90728b (MDEV-16809)
    we introduced the configuration option innodb_log_optimize_ddl
    for controlling whether native index creation or table-rebuild
    in InnoDB should avoid writing full redo log.
    
    Fungo Wang reported that this option is causing occasional failures.
    The reason is that pages may be written to data files in an
    inconsistent state. Applying log records to such inconsistent pages
    may fail.
    
    The solution is to always invoke PageBulk::finish() before page latches
    may be released, to ensure that the page contents is in a consistent
    state.
    
    Something similar was implemented in MySQL 8.0.13:
    mysql/mysql-server@d1254b947354e0f5b7223b09c521bd85f22e1e31
    
    buf_block_t::skip_flush_check: Remove. Suppressing consistency checks
    is a bad idea.
    
    PageBulk::needs_finish(): New predicate: Determine whether
    PageBulk::finish() must fix up the page.
    
    PageBulk::init(): Clear PAGE_DIRECTION to ensure that needs_finish()
    will hold. We change the field from PAGE_NO_DIRECTION to 0
    and back without writing redo log. This trick avoids the need
    to introduce any new data member to PageBulk.
    
    PageBulk::insert(): Replace some high-level accessors to bypass
    debug assertions related to PAGE_HEAP_TOP that we will be violating
    until finish() has been executed.
    
    PageBulk::finish(): Tolerate m_rec_no==0. We must invoke this also
    on an empty page, to ensure that PAGE_HEAP_TOP is initialized.
    
    PageBulk::commit(): Always invoke finish().
    
    PageBulk::release(), BtrBulk::pageSplit(), BtrBulk::storeExt(),
    BtrBulk::finish(): Invoke PageBulk::finish().
    147d4b1e
buf0buf.cc 203 KB