MySQL InnoDB Tuning: Configuring buffer pool, redo log, and flush

When the database hits the disk, all services suffer at once. We tune the InnoDB buffer pool turnkey: collect metrics under load, select flush modes, and hand over ready-made runbooks. Response time levels out, and heavy reports stop slowing down the entire service.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1365
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1113

Tuning InnoDB buffer pool: why the database is disk-bound

The first thing a disk-bound database reveals is the load profile: the share of reads from cache drops, the disk queue grows, and response spikes coincide in time not with the number of queries but with their nature.

It is worth comparing the buffer hit rate with the size of the working set: if the cache is smaller than the working set, every lookup by an index that is not in memory turns into a random read with all its latency.

The read bottleneck is usually not in the query itself. Slow queries under load appear where memory for the data cache is allocated on a residual basis: pages are evicted, immediately read again, and the same block migrates between disk and memory. Adding cores in such a situation does not help — processors idle while waiting for I/O.

By the evening peak the picture worsens: there are more connections, the hot set is wider, and the database's jagged response is more visible at high percentiles than in average time.

Background flushing of dirty pages and journal writes come in waves and compete with user queries for the same disk resources.

Tuning the InnoDB buffer pool begins with calculating the working set and the access pattern, not with “allocate more”: innodb_buffer_pool_size and the number of pool instances, journal size, page flushing method, and disk subsystem throughput are set in a coordinated way. Below we discuss how this is addressed.

What changes in database operation: response, downtime, failures

Tuning the innodb buffer pool primarily changes how the database responds to heavy queries.

When the working set of tables and indexes fits into the buffer pool, reads move from disk to memory, and database response time stops depending on whether a particular query hit the cache.

For aggregates over large tables this is a difference of multiples, not percentages: a query that previously waited for random disk accesses now fits into a predictable corridor.

The second effect is downtime due to load. A well-calibrated buffer pool size together with a separate redo log file eliminates swapping and disk I/O spikes during checkpoints.

The scheduler stops “getting stuck” on flushing dirty pages, so the spread between average and worst-case query shrinks rather than grows with traffic — response remains even during peak hours.

The third is a reduction in failures.

A whole class of crashes related to memory exhaustion goes away: when the buffer pool is set “by eye” and exceeds the memory available to the process, the service comes under system management and restarts, taking connections and unfinished transactions with it.

Careful dirty page flush thresholds and per-transaction commit mode provide stability under peak load without losing data safety guarantees during a power failure.

We verify the result by counters, not by feeling: the share of reads served from memory, the number of disk accesses per transaction, checkpoint duration and frequency, and the number of restarts.

MySQL exposes these metrics through standard observability tools, so the effect is visible on a graph before and after the configuration change.

Comparison of options: data cache, flush modes, integrity

Three parameters define database behavior under load: how much memory is allocated to the InnoDB data cache in MySQL, how often the change log is flushed to disk, and how strictly transaction integrity is checked on crash shutdown.

They are directly related: aggressive flushing preserves every committed operation but makes writes bottleneck on disk speed, while a large cache speeds up reads exactly until there is enough memory for the database processes themselves.

Option When appropriate What it entails
Log flush on every commit Payments, orders, any operations with stock and balances A committed transaction is never lost; writes are limited by disk
Flush once per second Most loaded services: catalog, profiles, logging Write spike is smoothed; on crash no more than the last second of operations is lost
Delayed flush Analytics, reports, intermediate calculations Maximum insert speed; on crash a noticeable portion of recent operations is lost
Data cache 60–75% of memory Server dedicated to one database Reads come from memory, disk is offloaded; if overflowed, the system goes into swapping
Data cache with headroom for processes Multiple databases or services on one server Server is resilient to peaks, but some reads still go to disk

The choice is made not by “maximum performance” but by the cost of loss: first we determine which operations must not be lost, and only then select the flush mode and cache size. We discuss how this is addressed for your load.

Work order: from collecting metrics to handing over procedures

We build the work order from measurements, not from standard recommendations: the same parameter values on different environments produce different effects — the read profile, write share, and daily peaks interfere.

Below is the sequence in which tuning the innodb buffer pool and flush modes does not break the current database operation.

  1. Collecting load metrics on production. We collect cache hit ratio, disk read volume, dirty page flush frequency, redo log waits, and query profile by hour. The observation window is at least a week; otherwise peaks and scheduled tasks will not make it into the report.
  2. Change plan. We fix target values and the relationships between them: cache size, dirty page threshold, flush intensity, and journal size are considered together, not as individual parameters.
  3. Phased implementation of changes. One step — one window: first a replica or data copy, then the production node, with a pause to collect metrics between steps.
  4. Verification under load. We compare the same metrics with the baseline: what matters is not only faster queries but also no increase in peak latency and no disk I/O spikes.
  5. Rollback plan. The original configuration is saved and versioned, a threshold is set at which rollback is triggered, and the time it takes for the node to return to its previous profile.
  6. Handover of procedures. We provide a parameter map with justification for each value, a link to the load profile, and a list of conditions under which the settings are reviewed: data growth, change in query nature, a new report.

Deliverables: configurations, diagrams, procedures

Tuning ends not with editing parameters but with a set of documents according to which the instance continues to live without the author of the changes.

We verify each document on a test environment: the on-duty engineer must act according to it without starting a correspondence with the developer.

  • Working configuration — a settings file broken into blocks: InnoDB buffer pool, redo log, dirty page flushing. Each value has a comment explaining what it depends on and when it is reviewed.
  • Configuration diagram — instance map: where data and logs live, how roles are distributed, and where read load goes.
  • Memory allocation diagram — how much is taken by the buffer pool, connections, and service structures, and what remains for the operating system so that a peak does not force it to swap memory to disk.
  • Database documentation — inventory of tables and indexes, heavy queries, growth signs that indicate it is time to revisit the settings.
  • Database maintenance procedure — planned maintenance windows, procedure for editing parameters, backup and recovery verification, rollback criteria.
  • Instructions for the on-duty shift — what to look at when latency grows and the log fills up, what is safe to change on the fly, and what only through a window.
  • Access policy — who reads metrics, who changes parameters, who confirms deployment, and where the audit trail remains.
  • Checklist for handing the database over to support — owners, test environments, monitoring and alerts, escalation points.

Case study: a heavy report stopped slowing down the entire service

The customer is a service with heavy analytics: a report over tens of millions of rows ran on a schedule and, while it was being built, hung the connection pool.

Other users during those minutes experienced a drop in service response — some queries timed out, and complaints arrived exactly during report hours. The InnoDB engine was operating normally, but it shared the same resource between the report and live traffic.

What the measurements showed

We collected metrics before the changes: the buffer pool size was smaller than the working data set, so each report pass evicted hot pages, and neighboring queries read them from disk again.

The second cause was the log flush mode: committing each write separately kept the disk busy during bulk inserts into temporary tables.

What we changed and what we got

We increased the pool to the size of the working set and split it into several independent areas — eviction of hot pages stopped. We switched log flushing to batch commit, and moved heavy reports to a separate replica so they would not compete with live queries.

Report build time decreased from about 40 minutes to 8, and the response of other queries during the report stopped differing from normal: p95 stays within its usual limits instead of increasing many times over.

Optimizing heavy reports here came down not to rewriting the query itself but to redistributing database resources.

This database case study is notable because the before-and-after results were collected using the same metrics and on the same data volume, so the comparison was fair.

What to do if stopping the database under load is unacceptable?

Most InnoDB parameters change on a running system.

Buffer pool size is redistributed in chunks, dirty page flush thresholds and I/O limits are picked up on the fly: the value is edited in memory, and the configuration file is written immediately — otherwise, after a scheduled restart, the database returns to the old profile.

A maintenance window is required by parameters that define engine geometry: the number of pool segments, the page flushing method, and page size. These values are read at startup and are not applied on the fly, so a restart is inevitable — the only question is its duration.

The duration of the window is determined not by database size but by preparation.

Running the new profile on a replica with production data volume, a pre-built config, a verified rollback plan, and a short stop instead of “let’s tune and see” — that way the window fits into minutes, not hours.

The main risk is an unscheduled database restart under load: after startup the buffer pool is empty, and queries go to disk until the working set warms up.

Therefore, pool warm-up and read queue monitoring are included in the plan in advance, along with MySQL tuning, not after an incident.

We review your configuration and load profile: which parameters we can apply without stopping, and for which we will plan a window and rollback procedure.

Questions asked before starting work

We address the doubts that most often come up during the evaluation stage: they do not require rewriting the application, because tuning the innodb buffer pool and write-ahead log is work with server configuration and the order of operations. Below are the things usually asked before the start.

Will there be enough memory for the increased buffer pool?

We calculate not “how much we would like” but how much remains for the operating system, connections, and background processes. If there is less headroom, we reduce the share and compensate by tuning dirty page flushing — the latency gain is preserved.

Will queries in the application need to be changed?

No. Pool and log parameters are changed on the server side; the application works over the same protocol. If a query plan relies on a missing index, that is a separate finding — we will show it, but we will not include it in the scope of this task.

You change things on a live server — will there be downtime?

Some parameters are applied on the fly, some require a restart. In the second case, we go node by node, and the service remains available. We confirm integrity by comparing checksums before and after the edits.

What about replicas and how is the result verified?

We recalculate values on replicas separately: they have a different load, and blindly copying the primary node settings causes lag. Before the change, we take baseline metrics — share of reads from memory, wait time on flush.

Afterward, we repeat the same measurement on the same load profile; the difference in numbers is the work report.

Let’s discuss the task and come back with an estimate and work plan

To make the estimate for InnoDB buffer pool tuning not “by eye,” the first conversation is usually enough: you describe what hurts — drops at peaks, growing response time, nighttime write spikes — and we ask clarifying questions about the load mode and current server configuration. This is enough to understand where the limit is and what will actually have an effect.

What we will need from you to start:

  • metrics for 2–4 weeks: CPU load, disk read and write operations, waits, working data set size;
  • current values of buffer pool, redo log sizes, flush mode, and number of connections — from the configuration or directly from the running database;
  • load profile in words: read and write share, heaviest queries, work with large tables and reports;
  • a window for changes: when a restart is acceptable and whether there is a replica where edits can be tested before production;
  • the contact of the engineer who will confirm the result after the changes, and a channel for coordination along the way.

In return, you receive a work plan for database tuning: which parameters we change, in what order, what we check after each step, and how we roll back if the metrics go the wrong way.

The timeline estimate comes in stages — diagnostics separately, changes separately, and post-change monitoring separately.

Describe your database optimization task in your own words — we will come back with an estimate and plan. We start a database project from the narrowest bottleneck, not from a complete server rebuild.