Skip to content
  • Inaam Rana's avatar
    b2b5ef13
    WL5580: Changes to LRU flushing (InnoDB) · b2b5ef13
    Inaam Rana authored
    Approved by: Marko, Sunny
    rb://589
    
    This work is performance related. The idea is to off load flushing
    activity that happens in the LRU list from user threads to the
    background thread i.e.: the page_cleaner. Also included in the scope is
    simpler and may be better heuristic for LRU flushing.
    
    Summary of Changes:
    
    New Config Options:
    ===================
    innodb_lru_scan_depth (default 1024): dynamic, min:100, max:~0
    innodb_flush_neighbors (default TRUE): dynamic
    innodb_doublewrite_batch_size (default 120) static, min 1, max 127
    (undocumented for internal testing only. enabled when
    UNIV_PERF_DEBUG is defined)
    
    New LRU flushing algorithm:
    ===========================
    * LRU flushing happens only in page_cleaner thread
    * LRU flushing includes cleaning the tail of LRU list AND putting
    blocks to the free list
    * When a user threads can't find a block in free list or a clean block
    in the tail of LRU then it triggers a new type of flush called
    BUF_FLUSH_SINGLE_PAGE in which it tries to flush a single page from LRU
    list instead of triggering a batch.
    
    Page eviction algorithm:
    ========================
    * iteration 0:
      * get a block from free list, success:done
      * if there is an LRU flush batch in progress:
        * wait for batch to end: retry free list
      * if buf_pool->try_LRU_scan is set
        * scan LRU up to srv_LRU_scan_depth to find a clean block
        * the above will put the block on free list
        * success:retry the free list
      * flush one dirty page from tail of LRU to disk
        * the above will put the block on free list
        * success: retry the free list
    * iteration 1:
      * same as iteration 0 except:
        * scan whole LRU list
        * scan LRU list even if buf_pool->try_LRU_scan is not set
    * iteration > 1:
      * same as iteration 1 but sleep 100ms
    
    Note that potential convoy problem where all user threads try to find
    a clean page in the tail of the LRU list when there is none is resolved
    by introducing buf_pool->try_LRU_scan flag which is set to TRUE when an
    LRU batch is completed and is set to FALSE when an LRU scan fails to
    find a clean page.
    
    Doublewrite buffer changes:
    ===========================
    The doublewrite buffer is split into two parts. First part is used
    for batch flushing (e.g.: LRU flushing and flush_list flushing) while
    the second part is used for single page flushes. The logic for the
    batch flushing remains same. For the single page flushing we use a
    flag to indicate if a slot is in use and we force a write to the disk
    after writing to the doublewrite buffer right away.
    
    There is an undocumented hidden config parameter
    innodb_doublewrite_batch_size which is visible only with
    UNIV_PERF_DEBUG or UNIV_DEBUG. The value determines how much of
    doublewrite is to be used for batch flushing. The default is 120 and 
    allowable values are 1 - 127. It is a static variable.
    
    LRU batch size:
    ===============
    The size of an LRU batch depends on how deep we scan the LRU
    list i.e.: innodb_LRU_scan_depth. But since user threads wait for an
    LRU batch to finish and since the size of doublewrite buffer is 128 it
    makes sense to divide one big LRU batch into multiple chunks.
    PAGE_CLEANER_LRU_BATCH_CHUNK_SIZE == 100 does that i.e.: after flushing
    100 pages the page cleaner signals waiting user threads to proceed to
    grab a free page.
    b2b5ef13
    WL5580: Changes to LRU flushing (InnoDB)
    Inaam Rana authored
    Approved by: Marko, Sunny
    rb://589
    
    This work is performance related. The idea is to off load flushing
    activity that happens in the LRU list from user threads to the
    background thread i.e.: the page_cleaner. Also included in the scope is
    simpler and may be better heuristic for LRU flushing.
    
    Summary of Changes:
    
    New Config Options:
    ===================
    innodb_lru_scan_depth (default 1024): dynamic, min:100, max:~0
    innodb_flush_neighbors (default TRUE): dynamic
    innodb_doublewrite_batch_size (default 120) static, min 1, max 127
    (undocumented for internal testing only. enabled when
    UNIV_PERF_DEBUG is defined)
    
    New LRU flushing algorithm:
    ===========================
    * LRU flushing happens only in page_cleaner thread
    * LRU flushing includes cleaning the tail of LRU list AND putting
    blocks to the free list
    * When a user threads can't find a block in free list or a clean block
    in the tail of LRU then it triggers a new type of flush called
    BUF_FLUSH_SINGLE_PAGE in which it tries to flush a single page from LRU
    list instead of triggering a batch.
    
    Page eviction algorithm:
    ========================
    * iteration 0:
      * get a block from free list, success:done
      * if there is an LRU flush batch in progress:
        * wait for batch to end: retry free list
      * if buf_pool->try_LRU_scan is set
        * scan LRU up to srv_LRU_scan_depth to find a clean block
        * the above will put the block on free list
        * success:retry the free list
      * flush one dirty page from tail of LRU to disk
        * the above will put the block on free list
        * success: retry the free list
    * iteration 1:
      * same as iteration 0 except:
        * scan whole LRU list
        * scan LRU list even if buf_pool->try_LRU_scan is not set
    * iteration > 1:
      * same as iteration 1 but sleep 100ms
    
    Note that potential convoy problem where all user threads try to find
    a clean page in the tail of the LRU list when there is none is resolved
    by introducing buf_pool->try_LRU_scan flag which is set to TRUE when an
    LRU batch is completed and is set to FALSE when an LRU scan fails to
    find a clean page.
    
    Doublewrite buffer changes:
    ===========================
    The doublewrite buffer is split into two parts. First part is used
    for batch flushing (e.g.: LRU flushing and flush_list flushing) while
    the second part is used for single page flushes. The logic for the
    batch flushing remains same. For the single page flushing we use a
    flag to indicate if a slot is in use and we force a write to the disk
    after writing to the doublewrite buffer right away.
    
    There is an undocumented hidden config parameter
    innodb_doublewrite_batch_size which is visible only with
    UNIV_PERF_DEBUG or UNIV_DEBUG. The value determines how much of
    doublewrite is to be used for batch flushing. The default is 120 and 
    allowable values are 1 - 127. It is a static variable.
    
    LRU batch size:
    ===============
    The size of an LRU batch depends on how deep we scan the LRU
    list i.e.: innodb_LRU_scan_depth. But since user threads wait for an
    LRU batch to finish and since the size of doublewrite buffer is 128 it
    makes sense to divide one big LRU batch into multiple chunks.
    PAGE_CLEANER_LRU_BATCH_CHUNK_SIZE == 100 does that i.e.: after flushing
    100 pages the page cleaner signals waiting user threads to proceed to
    grab a free page.
Loading