Bug #69122 InnoDB doesn't redo-log insert buffer merge operation if it is done in-place
Submitted: 2 May 2013 6:06 Modified: 12 Sep 2013 19:55
Reporter: Nizameddin Ordulu Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S3 (Non-critical)
Version:5.1,5.6 OS:Any
Assigned to: CPU Architecture:Any
Tags: crash recovery, insert buffer

[2 May 2013 6:06] Nizameddin Ordulu
Description:
InnoDB doesn't write a transaction log record when it merges a record from the insert buffer to an index page if the insertion is performed as an update-in-place. 

The related function is ibuf_insert_to_index_page(). At some point in the function innodb checks if the record from the insert buffer can be inserted to the index by updating an existing record in the index:

		if (!row_upd_changes_field_size_or_external(index, offsets,
							    update)
		    && (!page_zip || btr_cur_update_alloc_zip(
				page_zip, block, index,
				rec_offs_size(offsets), FALSE,
				rec_get_heap_no_new(rec), mtr, mtr->trx))) {
			/* This is the easy case. Do something similar
			to btr_cur_update_in_place(). */
			row_upd_rec_in_place(rec, index, offsets,
					     update, page_zip);
			goto updated_in_place;
		}

Now the update happens in row_upd_rec_in_place() but this function doesn't write to the redo-log. In fact nothing writes this operation to the redo log. As such, if innodb crashes before the secondary index page is flushed the secondary index page would miss the record after recovery.

How to repeat:
Read code. I did not write a test for it.

Suggested fix:
call btr_cur_update_in_place_log() after row_upd_rec_in_place() in ibuf_insert_to_index_page().
[2 May 2013 6:20] Marko Mäkelä
This is a regression from fixing
Bug#56680 InnoDB may return wrong results from a case-insensitive covering index
[12 Sep 2013 19:55] Bugs System
Noted in 5.1.73, 5.5.35, 5.6.15, 5.7.3 changelogs:

When the change buffer is enabled, "InnoDB" would fail to write a
transaction log record when merging a record from the insert buffer to a
secondary index page if the insert was performed as an "update-in-place".
[5 Dec 2013 6:37] Laurynas Biveinis
5.1$ bzr log -r 4047
------------------------------------------------------------
revno: 4047
committer: Satya Bodapati <satya.bodapati@oracle.com>
branch nick: mysq-5.1
timestamp: Wed 2013-09-11 16:57:02 +0530
message:
  Bug#16752251 - INNODB DOESN'T REDO-LOG INSERT BUFFER MERGE OPERATION IF
  	       IT IS DONE IN-PLACE
  
  With change buffer enabled, InnoDB doesn't write a transaction log
  record when it merges a record from the insert buffer to an secondary
  index page if the insertion is performed as an update-in-place.
  
  Fixed by logging the 'update-in-place' operation on secondary index
  pages.
  
  Approved by Marko. rb#2429
[5 Dec 2013 6:38] Laurynas Biveinis
5.1$ bzr log -r 4048
------------------------------------------------------------
revno: 4048
committer: Satya Bodapati <satya.bodapati@oracle.com>
branch nick: mysql-5.1
timestamp: Thu 2013-09-12 12:28:16 +0530
message:
  Additional Fix to BUG#16755251 for 5.1 build failure and 
  disable testcase due to BUG#17446090
[2 Feb 2014 17:47] Laurynas Biveinis
5.5$ bzr log -r 4567
------------------------------------------------------------
revno: 4567
committer: Satya Bodapati <satya.bodapati@oracle.com>
branch nick: mysql-5.5
timestamp: Thu 2013-12-26 14:33:52 +0530
message:
  BUG#16752251 - INNODB DOESN'T REDO-LOG INSERT BUFFER MERGE OPERATION IF
                 IT IS DONE IN-PLACE
  
  Add testcase as innodb-change-buffer-recovery.test