Bug #77783 performance dropped when changing innodb_change_buffering from inserts to all
Submitted: 20 Jul 2015 7:01 Modified: 25 Oct 2019 12:00
Reporter: zhai weixiang (OCA) Email Updates:
Status: Can't repeat Impact on me:
Category:MySQL Server: InnoDB storage engine Severity:S5 (Performance)
Version:5.7, 5.6 OS:Any
Assigned to: CPU Architecture:Any

[20 Jul 2015 7:01] zhai weixiang
while changing our default setting of innodb_change_buffering from inserts to all,  I observed a very obvious tps decreasing immediately  (almost from 17000 inserts/s to 6000 inserts/s).

The main workload is INSERT, you can easily repeat the TPS decreasing with the following step:

1. small buffer pool size, and innodb_change_buffering=inserts
2. create table with some of secondary indexes
3. keep inserting records into the table
...after a while, set innodb_change_buffering = all 

This is because  when innodb_change_buffering = inserts,  the counter area (IBUF_REC_OFFSET_COUNTER) of ibuf entry is not set and use the old format to build the ibuf entry. 

If innodb_change_buffering is not equal to INSERTS or NONE,  it need to read the counter value of previous ibuf  entry on the same page,  and check if it equals to ULINT_UNDEFINED. if yes, then consider current change buffering failed.

quoted code from ibuf_insert_low:

3544         if (!no_counter) {
3545                 /* Patch correct counter value to the entry to
3546                 insert. This can change the insert position, which can
3547                 result in the need to abort in some cases. */
3548                 ulint           counter = ibuf_get_entry_counter(
3549                         page_id.space(), page_id.page_no(),
3550                         btr_pcur_get_rec(&pcur), &mtr,
3551                         btr_pcur_get_btr_cur(&pcur)->low_match
3552                         < IBUF_REC_FIELD_METADATA);
3553                 dfield_t*       field;
3555                 if (counter == ULINT_UNDEFINED) {
3556                         ibuf_mtr_commit(&bitmap_mtr);
3557                         goto fail_exit;
3558                 }

This means we can buffer new operation only after all previous ibuf entries are merged...

How to repeat:
described above or read the code

Suggested fix:
I don't know. 
May be we can always write the counter value even innodb_change_buffering is equal to INSERTS ?
[24 Sep 2019 14:02] MySQL Verification Team

Thank you Mr. weixiang. However, I do not see what is a bug here. When the value of that variable is set to INSERTS, then you get much higher performance with those DMLs.

Hence, what is a problem.

If you have an idea about the mistake in the code and how it could be mitigated, please share it with us.
[25 Oct 2019 1:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".