During any MySQL major version upgrade, especially when moving from 8.0 to 8.4, it’s not just about compatibility checks. Subtle default changes can directly impact MySQL performance tuning, and if you’re not watching closely, they can show up as unexpected latency or throughput issues.
This is a tale from a MySQL 8.4 upgrade causing write latency and the default changes of innodb_change_buffering.
InnoDB’s change buffer (innodb_change_buffering) used to be an important optimisation for write-heavy workloads. However, in MySQL 8.4, it is disabled by default. Remember, it is disabled, not deprecated (at least as of now).
This blog post walks through a small but practical use case and what it means for real-world systems.
What the change buffer was for
InnoDB’s change buffer (formerly insert buffer) was designed for secondary indexes when the required leaf page is not present in the buffer pool.
Instead of performing a random read to fetch that page just to apply an insert, delete-mark, or purge operation, InnoDB records the change in the change buffer and merges it later.
On spinning disks, where random seeks were expensive and sequential I/O was cheaper, this provided a real performance benefit and played a role in MySQL write optimization. I have it covered in my previous blog / podcast below.
Reference: https://kedar.nitty-witty.com/blog/mysql-change-buffer-what-when-and-faq
Podcast: https://www.youtube.com/watch?v=vt78zI_fwfU
Why is innodb_change_buffering off by default in 8.4?
(drive slow, sharp U turn ahead)
1. Database hardware has changed
On most modern systems, storage is SSD/NVMe or RAID-backed, where random I/O is significantly faster compared to traditional HDDs.
The original benefit of change buffering was to avoid slow random disk reads for secondary index updates. That bottleneck largely no longer exists.
So effectively:
If random I/O is no longer expensive, avoiding it brings less value for most MySQL workloads.
2. Additional overhead
Maintaining the change buffer is not free.
– Extra writes
– Additional metadata tracking
– Background merge operations
All of this adds overhead to write operations and can impact MySQL query performance, especially under sustained write load.
Source: mysql-8-4-lts-new-production-ready-defaults-for-innodb
So question arise:
Does the optimization still justify the cost?
In my understanding, this is not a case of “Change buffer is useless” but rather “Change buffer is not beneficial enough”
This aligns with MySQL 8.4 LTS philosophy of more practical defaults for MySQL performance optimization:
innodb_change_buffering: all → none
Effectively disabling it out of the box. But why disable it and not remove it? I can’t speak on behalf of MySQL, but I’m actually glad it’s still there. BUT wait there is more to this story.
Let me first share what drew me to write this blog.
8.4 Upgrade and Write Latency
A “friend” of mine upgraded from MySQL 8.0 to 8.4 and quickly hit the panic button, as their write latency almost doubled. From ~2ms to ~4ms. Now, I may joke about it saying “dude, that’s just 2ms” but for latency-sensitive systems, that’s significant for database performance.
I know, you being a smart reader would have doubted innodb_change_buffering behaviour and so did I.
We reverted:
innodb_change_buffering = all
…and the latency dropped back to expected levels.
You probably already know this, and maybe I did bait you a bit with the “how to fix” title. But in reality, I just wanted to put this out there for someone who might find it useful.
and now it’s time for the “more to this story” or “sharp U turn”…
The Changing story of Change Buffering
I have been pointed out that in 9.5 release notes covers that innodb_change_buffering is again defaults to all. (thanks JFG, JS)… I had totally over-looked this part and only checked that it was not deprecated in 9.6.
We can take a hint from the commit log that gives us some reasoning for this change.
WL#16967 InnoDB : Enable innodb_change_buffer by default
Description: In 8.4, innodb_change_buffering was turned OFF (by setting it to NONE) by default due to certain stability issues identified with change buffering.
Now that these issues are fixed in 9.3, innodb_change_buffering can be turned ON (by setting it to ALL) by default in the 9.x LTS.Learning for MySQL users
What I understand here is, in MySQL 8.4 reason for change was “improved hardware” or “stability issues”. While in MySQL 9.5 / 9.6, the reason for the change was “stability improvements”.
Regardless, If I were the user, I’d stay with the default and review the latency impact. If the impact is negative, I’d adjust the innodb_change_buffering to “all” (or whatever was my previous settings) and observe. Also remember, this default changes back to “all” in MySQL 9.6.
Maybe it will stay, maybe it won’t. Defaults have already shifted, and future versions may evolve further as MySQL continues to refine… but this brings us to the important takeaway:
Always test every aspect of your workload during a MySQL upgrade.
Especially when even a few milliseconds of latency change can have real impact on MySQL performance tuning and query optimization.
Final note
I recently covered a MySQL Major Version Upgrade Checklist in a podcast, focused on practical upgrade strategies, validation steps, and avoiding surprises like this one.
If you’re planning an upgrade, it might be a useful reference.
4 comments
The default changes back to “all” on MySQL 9.7 – there were reported crashes with the change buffer in 8.4 so the default was changed but that stability is now back.
Thanks Justin, I updated the article to reflect the fact.
There is more to that story, I sent you some information about this in MySQL Community Slack.
Thanks JFG.