MySQL
8.0.xSummary
ACID-compliant relational database using the InnoDB storage engine with clustered primary key indexes, GTID-based replication, and a mature ecosystem of tooling for connection routing and horizontal sharding.
Primary Use Case
OLTP workloads requiring transactional integrity, high-concurrency reads via replicas, and row-level locking. Dominant in web application stacks; paired with ProxySQL for connection management and Vitess for sharding at scale.
Workload Fit
Strengths
Best for
- ·Web application OLTP workloads with well-defined access patterns via primary key or indexed columns
- ·Systems requiring ACID transactions with row-level locking and predictable single-query latency
- ·High read-to-write ratio workloads served by a primary + multiple replicas with ProxySQL routing
- ·Organizations with existing MySQL operational expertise where migration risk outweighs PostgreSQL feature advantages
- ·Sharded relational workloads at extreme scale using Vitess for transparent horizontal partitioning
Excels when
- ·Query patterns primarily access rows by primary key or narrow composite index: InnoDB's clustered key layout makes these very fast
- ·Read load is 10x+ write load and can be distributed across replicas
- ·Team has ProxySQL expertise to handle connection pooling and replica routing
- ·Write throughput fits on a single primary at up to 40k TPS with tuning
Architectural advantages
- ·Clustered primary key (row data IS the primary index) makes PK lookups extremely cache-efficient: no heap indirection
- ·GTID-based replication enables automated failover and replica re-pointing without manual binlog position tracking
- ·ProxySQL provides query routing, connection multiplexing, and query rewriting without application changes
- ·Vitess (CNCF) provides proven horizontal sharding at GitHub and YouTube scale on top of MySQL
- ·Mature ecosystem: Percona XtraBackup for hot physical backups, pt-query-digest for query analysis
- ·Clustered index ordering makes primary-key range scans read contiguous pages instead of scattered heap fetches: SELECT ... WHERE id BETWEEN x AND y is sequential I/O by construction, a property a heap-organized engine only gets after an explicit, non-maintained reclustering
- ·The redo log and binlog are independently sized and retained: crash-recovery log growth (redo log capacity) and replication/PITR retention (binlog) can be tuned separately without one policy compromising the other
When to Avoid
Avoid when
- ·Workload requires complex SQL features: partial indexes, array types, lateral joins, or advanced window functions available in PostgreSQL
- ·Write throughput requires horizontal scaling without a sharding layer: use CockroachDB or Vitess-on-MySQL
- ·Workload is primarily analytical: MySQL's row-oriented storage performs poorly on full-scan aggregation queries
Common misuses
- ·Using MySQL as an analytical warehouse: full-table scans on InnoDB row-oriented storage for OLAP queries cause sustained I/O contention on the primary
- ·Relying on MySQL ENUM type for values that change frequently: ALTERing an ENUM column requires a full table rebuild in older versions
- ·Not using the EXPLAIN FORMAT=JSON output before deploying queries: MySQL's optimizer can choose unexpected index strategies under variable data distributions
Consistency & Transactions
Scaling
Read scalability
Read replicas via GTID-based replication distribute read load. ProxySQL routes read queries to replicas and write queries to the primary. Practical ceiling is 8–10 replicas before replication topology monitoring becomes unwieldy.
Write scalability
Single-primary write path. Vertical scaling is the primary write lever. Beyond a single primary, Vitess provides application-transparent horizontal sharding; MySQL Group Replication offers multi-primary but with conflict detection overhead.
Failure Behavior
Known failure modes
- ·Replication lag on write-heavy workloads causes stale reads on replicas; GTID lag must be monitored continuously
- ·Long-running transactions holding row locks block subsequent writes on the same rows indefinitely
- ·InnoDB deadlock cycles under high-concurrency mixed read-write workloads; applications must handle ER_LOCK_DEADLOCK and retry
- ·Binary log retention misconfiguration causes disk exhaustion when a replica goes offline and the primary retains binlog for it
- ·Secondary index indirection: a secondary index lookup for a non-covered column finds the primary key, then a second traversal into the clustered index finds the row, doubling B-tree reads on covering-index misses at sustained write/read throughput (see secondary_index_saturation)
- ·Group Replication certification conflicts under high contention cause transaction rollbacks that are invisible to applications not checking for ER_TRANSACTION_ROLLBACK_DURING_COMMIT
- ·Undersized redo log capacity forces InnoDB's fuzzy checkpointing into more frequent synchronous checkpoints, stalling writes; oversizing it extends crash-recovery replay time (see checkpoint_amplification)
- ·Redo log and binlog growth outrunning disk bandwidth or replica apply rate stalls commits and, for the binlog, can exhaust disk if a replica or CDC consumer falls behind (see wal_saturation)
Bottlenecks
- ·Single-primary write path cannot be horizontally scaled without Vitess or application-layer sharding
- ·Secondary index indirection: a covering-index miss requires a second B-tree traversal from the secondary index into the clustered primary key to fetch the row, doubling random reads for that query shape (see secondary_index_saturation)
- ·Connection overhead under high concurrency: MySQL uses one OS thread per connection; ProxySQL is mandatory at >500 concurrent connections
- ·Long transactions hold row locks and inflate InnoDB history list length, degrading read performance for all queries
- ·Binlog-based replication is synchronous commit on primary but asynchronous delivery to replicas: replica lag is inevitable under write bursts
- ·Redo log size vs. checkpoint frequency tradeoff: a small innodb_redo_log_capacity (or the older innodb_log_file_size/innodb_log_files_in_group pair) gives fuzzy checkpointing less room to spread dirty-page flushes and forces more frequent synchronous checkpoints under sustained write load, while a larger redo log extends crash-recovery replay time (see checkpoint_amplification)
Degradation patterns
- ·InnoDB history list length grows when long-running read transactions prevent purge of old row versions: read latency increases as purge queue depth rises
- ·Replication lag accumulates during large batch writes that produce large binlog events; replicas fall behind and stale reads silently increase
- ·Connection storms during primary failover: applications not behind ProxySQL open new connections directly and overwhelm the new primary
- ·Forced synchronous checkpoints under sustained high-write load when the redo log approaches capacity: unlike PostgreSQL's clock-driven checkpoint spikes, this is load-driven, InnoDB's page cleaner flushes more aggressively as redo log space or the buffer pool's dirty-page fraction nears its ceiling (see checkpoint_amplification)
Recovery considerations
- ·GTID-based replication enables replica re-pointing to a new primary without manual binlog coordinates: requires gtid_mode=ON and enforce_gtid_consistency=ON before failure
- ·Percona XtraBackup provides non-locking physical backups; mysqldump creates a global lock for the duration of the dump on non-InnoDB tables
- ·Semi-synchronous replication reduces data loss window during failover at the cost of write latency when replica acknowledgement times out
Operational Pitfalls
- ·Not deploying ProxySQL: direct application connections to MySQL primary cause connection storms during failover and cannot route reads to replicas
- ·Using MyISAM tables in any capacity: MyISAM has table-level locking and no crash recovery; all tables must be InnoDB
- ·Selecting wide rows without covering indexes: InnoDB secondary index lookups traverse to the clustered primary index for every row returned
- ·Ignoring slow query log: MySQL's slow_query_log with long_query_time=0.1 is the primary tool for identifying missing indexes before they cause production incidents
- ·Not tuning innodb_buffer_pool_size: defaults to 128MB; should be 70–80% of available RAM on a dedicated MySQL host
- ·Running INFORMATION_SCHEMA.INNODB_TRX queries infrequently during lock contention: active transactions and their blocking chains must be monitored in real time
Architecture Guidance
Common topology roles
Migration notes
- ·From PostgreSQL: MySQL lacks partial indexes, array columns, and CTEs with UPDATE: application queries must be rewritten for these patterns
- ·To Vitess: existing unsharded MySQL can be migrated to Vitess using the MoveTables workflow without downtime; requires careful vindex selection
- ·To Aurora MySQL: wire-compatible but Aurora's distributed storage layer has different I/O characteristics: benchmark write-heavy workloads before migration
Advisor Guidance
When: scenario has high connection count or connection-heavy workload
Deploy ProxySQL in front of MySQL primary; configure read/write split rules to route SELECT statements to replicas
When: scenario requires horizontal write scaling beyond a single primary
Evaluate Vitess for transparent MySQL sharding; define vindex strategy based on primary access patterns before schema design is finalized
When: scenario uses CDC or event streaming
Configure MySQL binlog with ROW format for accurate change events; use Debezium MySQL connector for CDC pipeline
Comparison Factors
operational complexity
Medium: ProxySQL configuration and replication monitoring add operational surface; simpler than CockroachDB or Vitess
write scalability
Single-primary; sharding requires Vitess middleware which adds very high operational overhead
consistency guarantee
Full ACID with row-level locking; semi-sync replication narrows failover data loss window
ecosystem maturity
Most widely deployed open-source relational database; deep tooling ecosystem (Percona, ProxySQL, Vitess)
Managed Cloud Options
Enables Patterns
Basis
Extensive production documentation from GitHub, Facebook, and Percona; behavior well-characterized across a decade of at-scale deployments
Sources & Claims
InnoDB stores data physically ordered by the primary key (clustered index); if no primary key is declared, InnoDB clusters on the first UNIQUE NOT NULL index instead, and if neither exists, InnoDB generates an internal hidden 6-byte row ID to cluster on
pendingofficial documentation · MySQL 8.0 Reference Manual, InnoDB Clustered and Secondary Indexes
storage-engine-internals-spine batch 5
Every InnoDB secondary index stores the indexed column(s) plus a copy of the primary key value rather than a pointer to the physical row; a lookup via a secondary index for a column not covered by that index requires a second B-Tree traversal into the clustered index to fetch the row
pendingofficial documentation · MySQL 8.0 Reference Manual, InnoDB Clustered and Secondary Indexes
storage-engine-internals-spine batch 5
InnoDB's doublewrite buffer writes changed pages to a contiguous doublewrite storage area before writing them to their real data file locations, protecting against torn (partial) page writes during a crash; this serves a purpose functionally similar to PostgreSQL's full_page_writes but is a structurally different mechanism, a separate buffer area rather than a full-page image embedded in the durability log
pendingofficial documentation · MySQL 8.0 Reference Manual, InnoDB Doublewrite Buffer
storage-engine-internals-spine batch 5
InnoDB maintains two structurally separate logs: the redo log, a fixed-size circular file used strictly for crash recovery, and the binary log (binlog), a separate log used for replication and point-in-time recovery with its own independent retention policy
pendingofficial documentation · MySQL 8.0 Reference Manual, InnoDB Redo Log, and The Binary Log
storage-engine-internals-spine batch 5
innodb_buffer_pool_size is the primary configuration variable controlling the size of the InnoDB buffer pool
pendingofficial documentation · MySQL 8.0 Reference Manual, innodb_buffer_pool_size system variable
storage-engine-internals-spine batch 5
InnoDB's buffer pool LRU list uses a midpoint insertion strategy dividing the list into young and old sublist regions, intended to prevent large one-time scans from evicting frequently-accessed pages from cache
pendingofficial documentation · MySQL 8.0 Reference Manual, Buffer Pool LRU Algorithm
storage-engine-internals-spine batch 5; exact sublist size ratio and other numeric tuning defaults intentionally not asserted, version-sensitive
Related Architecture Knowledge
Outbound: this entity affects
MySQL with statement-based binlog replication is vulnerable to replica divergence when SQL contains non-deterministic functions; row-based replication eliminates this vulnerability.
Full relationship →