Skip to content
  • Marko Mäkelä's avatar
    5b38f2a7
    Bug#14606334 INNODB UNABLE TO MERGE IBUF INTO PAGE · 5b38f2a7
    Marko Mäkelä authored
    Bug#14774779 CRASH RECOVERY FAILED, UNABLE TO COMPRESS A PAGE
    
    Whenever we successfully reorganize or compress a compressed secondary
    index page, ensure that the IBUF_BITMAP_FREE bits will be updated
    accordingly. Also, slightly change the definition of IBUF_BITMAP_FREE
    in compressed pages. Instead of considering the free space on the
    uncompressed page *after* reorganize, use the *before* value, so that
    a buffered insert can be merged without reorganizing or even recompressing
    the page.
    
    btr_page_reorganize_low(), btr_page_reorganize(),
    btr_cur_update_alloc_zip_func(), btr_cur_insert_if_possible(),
    page_cur_tuple_insert(), page_cur_rec_insert(),
    page_cur_insert_rec_zip(), page_copy_rec_list_end_to_created_page(),
    page_copy_rec_list_end_no_locks(), page_copy_rec_list_end(),
    page_copy_rec_list_start(), page_move_rec_list_end(),
    page_move_rec_list_start(): Note that the caller should keep
    IBUF_BITMAP_FREE up to date.
    
    btr_page_split_and_insert(): On failure, reset the IBUF_BITMAP_FREE
    bits on both pages.
    
    btr_cur_optimistic_delete_func(): Do not update the IBUF_BITMAP_FREE
    on compressed pages any more, because according to the updated
    definition, it will not increase by purging records without
    reorganizing the page.
    
    btr_cur_optimistic_insert(), btr_cur_update_in_place(),
    btr_cur_optimistic_update(), btr_cur_pessimistic_update(): After a
    failed attempt to modify a compressed page, reset the IBUF_BITMAP_FREE
    bits, because we may already have reorganized the page.
    
    btr_cur_update_in_place(), btr_cur_optimistic_update():
    Implement the flag BTR_KEEP_IBUF_BITMAP for suppressing the
    IBUF_BITMAP_FREE updates, so that btr_cur_pessimistic_update()
    can invoke btr_cur_compress_if_useful() without violating the
    latching order (further pages cannot be latched after latching
    a change buffer bitmap page).
    
    ibuf_index_page_calc_free_zip(): Consider the maximum insert size
    on the uncompressed page without reorganizing the page, so that
    ibuf_insert_to_index_page_low() will succeed without reorganizing
    or recompressing the page.
    
    Fix a recovery problem in innodb_log_compressed_pages=OFF and
    reintroduce the parameter innodb_log_compressed_pages=OFF (ON by default).
    
    Also, whenever a page becomes empty, create the page from the
    scratch. This should hopefully generate less redo log, and it will
    reduce the cases where we are compressing garbage. This is also
    necessary in order to avoid an infinite page split with the rest of
    this patch.
    
    page_compression_level: Renamed to page_zip_level.
    
    page_log_compressed_pages: Renamed to page_zip_log_pages.
    
    innodb_compression_level_update(): Remove. Declare page_zip_level
    directly with a compatible data type.
    
    page_is_empty(): A new predicate, similar to page_is_leaf(), for
    checking PAGE_N_RECS == 0 without adjusting the endianness.
    
    page_has_garbage(): New predicate for checking if PAGE_GARBAGE is nonzero.
    
    page_create_empty(): New function, to replace a B-tree page with an
    empty page.
    
    page_create_zip(): Add a parameter for PAGE_MAX_TRX_ID, so that we can
    recreate a page without zeroing out the field. This field only needs
    to be nonzero on nonempty secondary index leaf pages.
    
    page_cur_insert_rec_zip_reorg(): Remove (merge to the only caller).
    
    page_cur_insert_rec_zip(): Take 'cursor' as a parameter. When not in
    crash recovery (applying redo log), modify the behaviour if there is
    not enough room in the page modification log (that is, page_zip_available()
    fails).
    If the page is logically empty, invoke page_create_zip() to
    physically empty the page.
    Otherwise, if the page contains no garbage and no modification log, give up.
    Otherwise, if innodb_log_compressed_pages=OFF, first do
    btr_page_reorganize_low() and only then attempt an insert followed by
    compressing the whole page. If innodb_log_compressed_pages=ON, insert
    into the uncompressed page only, and then invoke
    page_zip_reorganize(). In this way, whenever we have to recompress,
    we will always end up with a reorganized page with 1 or 0 record in
    the page modification log.
    
    page_cur_delete_rec(), page_delete_rec_list_end(),
    page_delete_rec_list_start(): If the page would become logically
    empty, invoke page_create_empty() to physically empty it.
    
    btr_page_reorganize_low(): Replace the 'block' parameter with
    'page_cur', and position the cursor on the same record, so that the
    caller will avoid the repositioning. Do not write a redo log record
    unless the operation succeeds.
    
    btr_cur_insert_if_possible(): Pass the cursor to
    btr_page_reorganize(), avoiding the costly page_cur_search() call.
    
    btr_cur_optimistic_insert(): After a failed page_cur_tuple_insert(),
    do not attempt page reorganize on a compressed page. The
    page_cur_tuple_insert() will already have attempted it, in vain.
    On uncompressed pages, pass the cursor to btr_page_reorganize() to
    avoid the page_cur_search() call.
    
    btr_cur_update_alloc_zip_func(): Renmed from
    btr_cur_update_alloc_zip(). Make offsets a debug-only
    parameter. Replace 'block' with 'cursor'. If there is not enough
    place, reorganize the page (to get rid of garbage in the PAGE_FREE
    list) rather than just recompress it. Give up if there is neither
    garbage in the PAGE_FREE list nor any modification log.
    
    btr_cur_update_in_place(): Make 'offsets' non-const, because
    btr_cur_update_alloc_zip() can now change the rec_offs_validate()
    information when it is reorganizing the page.
    
    NOTE: If we were free to change the redo log format, we could do the
    following when there is not enough place in the modification log to
    log an insert or update:
    
    * Reorganize the uncompressed page only.
    * Make the modification on the uncompressed page only.
      (These would need new redo log entry types.)
    * Compress the entire page. Redo logged as MLOG_ZIP_PAGE_COMPRESS_NO_DATA.
    
    If the compress operation fails, none of the redo log must be written,
    and we will have to restore the uncompressed page from the compressed
    page and refuse the operation.
    
    rb#1761 approved by Inaam Rana
    5b38f2a7
    Bug#14606334 INNODB UNABLE TO MERGE IBUF INTO PAGE
    Marko Mäkelä authored
    Bug#14774779 CRASH RECOVERY FAILED, UNABLE TO COMPRESS A PAGE
    
    Whenever we successfully reorganize or compress a compressed secondary
    index page, ensure that the IBUF_BITMAP_FREE bits will be updated
    accordingly. Also, slightly change the definition of IBUF_BITMAP_FREE
    in compressed pages. Instead of considering the free space on the
    uncompressed page *after* reorganize, use the *before* value, so that
    a buffered insert can be merged without reorganizing or even recompressing
    the page.
    
    btr_page_reorganize_low(), btr_page_reorganize(),
    btr_cur_update_alloc_zip_func(), btr_cur_insert_if_possible(),
    page_cur_tuple_insert(), page_cur_rec_insert(),
    page_cur_insert_rec_zip(), page_copy_rec_list_end_to_created_page(),
    page_copy_rec_list_end_no_locks(), page_copy_rec_list_end(),
    page_copy_rec_list_start(), page_move_rec_list_end(),
    page_move_rec_list_start(): Note that the caller should keep
    IBUF_BITMAP_FREE up to date.
    
    btr_page_split_and_insert(): On failure, reset the IBUF_BITMAP_FREE
    bits on both pages.
    
    btr_cur_optimistic_delete_func(): Do not update the IBUF_BITMAP_FREE
    on compressed pages any more, because according to the updated
    definition, it will not increase by purging records without
    reorganizing the page.
    
    btr_cur_optimistic_insert(), btr_cur_update_in_place(),
    btr_cur_optimistic_update(), btr_cur_pessimistic_update(): After a
    failed attempt to modify a compressed page, reset the IBUF_BITMAP_FREE
    bits, because we may already have reorganized the page.
    
    btr_cur_update_in_place(), btr_cur_optimistic_update():
    Implement the flag BTR_KEEP_IBUF_BITMAP for suppressing the
    IBUF_BITMAP_FREE updates, so that btr_cur_pessimistic_update()
    can invoke btr_cur_compress_if_useful() without violating the
    latching order (further pages cannot be latched after latching
    a change buffer bitmap page).
    
    ibuf_index_page_calc_free_zip(): Consider the maximum insert size
    on the uncompressed page without reorganizing the page, so that
    ibuf_insert_to_index_page_low() will succeed without reorganizing
    or recompressing the page.
    
    Fix a recovery problem in innodb_log_compressed_pages=OFF and
    reintroduce the parameter innodb_log_compressed_pages=OFF (ON by default).
    
    Also, whenever a page becomes empty, create the page from the
    scratch. This should hopefully generate less redo log, and it will
    reduce the cases where we are compressing garbage. This is also
    necessary in order to avoid an infinite page split with the rest of
    this patch.
    
    page_compression_level: Renamed to page_zip_level.
    
    page_log_compressed_pages: Renamed to page_zip_log_pages.
    
    innodb_compression_level_update(): Remove. Declare page_zip_level
    directly with a compatible data type.
    
    page_is_empty(): A new predicate, similar to page_is_leaf(), for
    checking PAGE_N_RECS == 0 without adjusting the endianness.
    
    page_has_garbage(): New predicate for checking if PAGE_GARBAGE is nonzero.
    
    page_create_empty(): New function, to replace a B-tree page with an
    empty page.
    
    page_create_zip(): Add a parameter for PAGE_MAX_TRX_ID, so that we can
    recreate a page without zeroing out the field. This field only needs
    to be nonzero on nonempty secondary index leaf pages.
    
    page_cur_insert_rec_zip_reorg(): Remove (merge to the only caller).
    
    page_cur_insert_rec_zip(): Take 'cursor' as a parameter. When not in
    crash recovery (applying redo log), modify the behaviour if there is
    not enough room in the page modification log (that is, page_zip_available()
    fails).
    If the page is logically empty, invoke page_create_zip() to
    physically empty the page.
    Otherwise, if the page contains no garbage and no modification log, give up.
    Otherwise, if innodb_log_compressed_pages=OFF, first do
    btr_page_reorganize_low() and only then attempt an insert followed by
    compressing the whole page. If innodb_log_compressed_pages=ON, insert
    into the uncompressed page only, and then invoke
    page_zip_reorganize(). In this way, whenever we have to recompress,
    we will always end up with a reorganized page with 1 or 0 record in
    the page modification log.
    
    page_cur_delete_rec(), page_delete_rec_list_end(),
    page_delete_rec_list_start(): If the page would become logically
    empty, invoke page_create_empty() to physically empty it.
    
    btr_page_reorganize_low(): Replace the 'block' parameter with
    'page_cur', and position the cursor on the same record, so that the
    caller will avoid the repositioning. Do not write a redo log record
    unless the operation succeeds.
    
    btr_cur_insert_if_possible(): Pass the cursor to
    btr_page_reorganize(), avoiding the costly page_cur_search() call.
    
    btr_cur_optimistic_insert(): After a failed page_cur_tuple_insert(),
    do not attempt page reorganize on a compressed page. The
    page_cur_tuple_insert() will already have attempted it, in vain.
    On uncompressed pages, pass the cursor to btr_page_reorganize() to
    avoid the page_cur_search() call.
    
    btr_cur_update_alloc_zip_func(): Renmed from
    btr_cur_update_alloc_zip(). Make offsets a debug-only
    parameter. Replace 'block' with 'cursor'. If there is not enough
    place, reorganize the page (to get rid of garbage in the PAGE_FREE
    list) rather than just recompress it. Give up if there is neither
    garbage in the PAGE_FREE list nor any modification log.
    
    btr_cur_update_in_place(): Make 'offsets' non-const, because
    btr_cur_update_alloc_zip() can now change the rec_offs_validate()
    information when it is reorganizing the page.
    
    NOTE: If we were free to change the redo log format, we could do the
    following when there is not enough place in the modification log to
    log an insert or update:
    
    * Reorganize the uncompressed page only.
    * Make the modification on the uncompressed page only.
      (These would need new redo log entry types.)
    * Compress the entire page. Redo logged as MLOG_ZIP_PAGE_COMPRESS_NO_DATA.
    
    If the compress operation fails, none of the redo log must be written,
    and we will have to restore the uncompressed page from the compressed
    page and refuse the operation.
    
    rb#1761 approved by Inaam Rana
Loading