• Marko Mäkelä's avatar
    MDEV-34750 SET GLOBAL innodb_log_file_size is not crash safe · 984606d7
    Marko Mäkelä authored
    The recent commit 4ca355d8 (MDEV-33894)
    caused a serious regression for online InnoDB ib_logfile0 resizing,
    breaking crash-safety unless the memory-mapped log file interface is
    being used. However, the log resizing was broken also before this.
    
    To prevent such regressions in the future, we extend the test
    innodb.log_file_size_online with a kill and restart of the server
    and with some writes running concurrently with the log size change.
    When run enough many times, this test revealed all the bugs that
    are being fixed by the code changes.
    
    log_t::resize_start(): Do not allow the resized log to start before
    the current log sequence number. In this way, there is no need to
    copy anything to the first block of resize_buf. The previous logic
    regarding that was incorrect in two ways. First, we would have to
    copy from the last written buffer (buf or flush_buf). Second, we failed
    to ensure that the mini-transaction end marker bytes would be 1
    in the buffer. If the source ib_logfile0 had wrapped around an odd number
    of times, the end marker would be 0. This was occasionally observed
    when running the test innodb.log_file_size_online.
    
    log_t::resize_write_buf(): To adjust for the resize_start() change,
    do not write anything that would be before the resize_lsn.
    Take the buffer (resize_buf or resize_flush_buf) as a parameter.
    Starting with commit 4ca355d8
    we no longer swap buffers when rewriting the last log block.
    
    log_t::append(): Define as a static function; only some debug
    assertions need to refer to the log_sys object.
    
    innodb_log_file_size_update(): Wake up the buf_flush_page_cleaner()
    if needed, and wait for it to complete a batch while waiting for
    the log resizing to be completed. If the current LSN is behind the
    resize target LSN, we will write redundant FILE_CHECKPOINT records to
    ensure that the log resizing completes. If the buf_pool.flush_list is
    empty or the buf_flush_page_cleaner() is stuck for some reason, our wait
    will time out in 5 seconds, so that we can periodically check if the
    execution of SET GLOBAL innodb_log_file_size was aborted. Previously,
    we could get into a busy loop here while the buf_flush_page_cleaner()
    would remain idle.
    984606d7
log0log.cc 37.2 KB