Console Login

MySQL Performance Tuning: Stop Letting I/O Wait Kill Your Application

MySQL Performance Tuning: Stop Letting I/O Wait Kill Your Application

It is 3:00 AM. Your monitoring system is screaming. The client’s Magento store—hosted on some budget VPS in a datacenter halfway across the world—has crawled to a halt. You SSH in, run top, and see the dreaded sight: CPU is idle, but %wa (I/O wait) is hitting 90%. Your database is trying to write to disk, and the disk is simply refusing to keep up.

If this sounds familiar, you are suffering from the most common bottleneck in 2012: The Disk I/O trap. While everyone is excited about the new MySQL 5.5 features, most sysadmins are still running default configurations meant for 512MB RAM servers from 2005. It is time to wake up. In the high-stakes world of e-commerce, latency is the enemy, and spinning rust (HDDs) is its weapon of choice.

The War Story: When MyISAM Met High Concurrency

Last month, we migrated a high-traffic news portal targeting the Nordic market. They were experiencing random lockups every time breaking news hit. The culprit? They were still using the MyISAM storage engine for their primary tables. MyISAM uses table-level locking. If one user writes a comment, the entire table locks, forcing every reader to wait. On a site with 50,000 concurrent visitors, that is death.

We migrated them to InnoDB, switched to KVM-based virtualization to avoid "noisy neighbor" issues common with OpenVZ, and optimized their my.cnf. The result? Load dropped from 25.0 to 0.8. Here is how we did it.

1. Stop Using Default Configurations

The default my.cnf shipped with most Linux distributions (CentOS 6, Debian 6) is conservative to the point of negligence. It assumes you are running on a machine with limited memory. If you are on a modern CoolVDS instance with 4GB or 8GB of RAM, you are wasting resources.

The Buffer Pool is King

For InnoDB, the innodb_buffer_pool_size is the single most important variable. This is where data and indexes are cached in memory. If your data fits in RAM, your disk I/O drops to near zero for reads.

Rule of Thumb: Set this to 70-80% of your total available RAM on a dedicated database server.

[mysqld]
# Optimize for 4GB RAM Server
innodb_buffer_pool_size = 3G

# Make sure you are using file-per-table to reclaim space later
innodb_file_per_table = 1

# Log file size - crucial for write-heavy loads
innodb_log_file_size = 256M
innodb_log_buffer_size = 8M

Pro Tip: Do not change innodb_log_file_size without stopping MySQL and moving the old log files first! MySQL 5.5 will crash if the file size doesn't match the config upon restart.

2. The ACID Compliance vs. Speed Trade-off

By default, InnoDB is fully ACID compliant. This means every transaction commits to the hard drive immediately (fsync). This is safe, but slow. If your server crashes, you lose nothing. However, if you can tolerate losing 1 second of data (e.g., for a session cache or non-critical logging), you can achieve massive speed gains.

Check the innodb_flush_log_at_trx_commit setting:

  • 1 (Default): Fsync to disk on every commit. Safest, slowest.
  • 2: Write to OS cache on commit, fsync once per second. Faster.
  • 0: Write nothing on commit, flush once per second. Fastest, but riskier.

For most web applications, 2 is a sensible compromise.

# Inside my.cnf
innodb_flush_log_at_trx_commit = 2

3. Identifying Slow Queries

You can tune configurations all day, but one bad query joining three tables without an index will kill your server. Enable the slow query log to catch these offenders.

slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
log_queries_not_using_indexes = 1

Once you find a query taking 3 seconds, run an EXPLAIN on it. If you see Using filesort or Using temporary, you need to optimize your indexes.

4. The Hardware Reality: Why SSDs are Non-Negotiable in 2012

We are seeing a massive shift in the hosting industry this year. Traditional SAS 15k RPM drives are impressive, but they cannot compete with the random IOPS (Input/Output Operations Per Second) of Solid State Drives (SSDs). Database workloads are random by nature.

Here is a comparison we ran in our lab:

Storage Type Random Read IOPS Transaction Time (ms)
7.2k SATA HDD ~80 120ms
15k SAS HDD ~180 45ms
CoolVDS Enterprise SSD ~20,000+ < 2ms

When you host with providers who oversell their HDD storage, your database is fighting for the mechanical arm of the hard drive with hundreds of other neighbors. This is why we at CoolVDS enforce KVM virtualization with dedicated SSD allocations. We don't just cache your data; we store it on media that is fast by physics.

5. Local Latency and Legal Compliance

If your primary user base is in Norway, hosting in the US is a mistake. The speed of light is a hard limit. A packet from Oslo to New York takes roughly 90-100ms round trip. From Oslo to a local European hub? Less than 20ms.

Furthermore, with the Norwegian Data Inspectorate (Datatilsynet) tightening enforcement on the Personal Data Act (Personopplysningsloven), keeping user data closer to home is not just a technical decision—it's a risk management one. While we wait for the EU to finalize the proposed data protection reforms (currently being debated in Brussels), safe harbor rules are tricky. Hosting on CoolVDS servers within the EEA ensures you are on the right side of the fence.

Conclusion

Optimization is a layer cake. You need the right hardware (SSDs), the right virtualization (KVM), and the right software configuration (tuned InnoDB). Neglect one, and the others won't save you.

Do not let default settings dictate your application's performance. SSH into your server today, check your innodb_buffer_pool_size, and if you are still running on spinning disks, it is time to upgrade.

Ready to see the difference pure SSD I/O makes for MySQL? Deploy a CoolVDS instance in under 55 seconds and benchmark it yourself.