Interview & expert mode
The module's closing argument. Sixty questions ordered by depth, with answers written the way you would actually say them; ten real production failures traced to their mechanism; and the MySQL-versus-Postgres comparison defended properly rather than as a list of features.
Sixty questions, ranked by depth
Answer each out loud before opening it. The ones you cannot answer name the chapter to reread.
Storage and indexing
Transactions and concurrency
Durability and recovery
Optimizer and performance
Memory, buffer pool, configuration
Replication and operations
Judgment
Ten war stories
Each of these is a real failure pattern. Read the symptom, try to name the mechanism before reading on.
ALTER TABLE on a small table hangs. Within a minute every query on that table is queued and the API is timing out.lock_wait_timeout so DDL fails fast, and audit the app for transactions left open across network calls.CHAR(36) UUIDv4 PK grew past the buffer pool. While the index fit in memory, random inserts were cheap; once it did not, every insert became a disk read to fetch its target page. The cliff arrives without warning.BINARY(16) with UUIDv7 or a Snowflake id. Short term, enlarge the buffer pool to buy time.trx_rseg_history_len.innodb_redo_log_capacity to several GB — dynamic since 8.0.30 — and raise innodb_io_capacity to match the NVMe hardware.sort_buffer_size and join_buffer_size to 8MB globally "for performance". At normal concurrency this was invisible; at 900 connections each running multi-join queries it exceeded RAM alongside the buffer pool.SELECT ... FOR UPDATE on a missing key took a gap lock. Gap locks are mutually compatible, so concurrent workers all held the same gap — then each insert needed an insert intention lock conflicting with the others'.INSERT ... ON DUPLICATE KEY UPDATE. Optionally READ COMMITTED to remove gap locks entirely.Seconds_Behind_Source = 0 for six hours. Then failover promoted a replica missing six hours of data.Replica_IO_Running and Replica_SQL_Running directly, and measure lag with a heartbeat table rather than the built-in counter.CONVERT TO CHARACTER SET utf8mb4. Add a schema check to CI.mysqldump existed. Restoring it took 14 hours, most of it rebuilding indexes.mysql_native_password by default. The driver could only speak that plugin, and the negotiation failure surfaces as an access-denied error rather than something informative.caching_sha2_password. The tell that distinguishes this from a credentials problem: it fails for every account, including new ones.MySQL versus Postgres, defended properly
Chapter 7 introduced the two foundational choices. Now the full argument, in both directions, because being able to argue the other side is what makes the position credible.
The two choices everything descends from
- Where the row lives. InnoDB clusters rows into the PK B+tree. Postgres uses an unordered heap with all indexes pointing into it.
- Where old versions go. InnoDB puts them in a separate undo log and rebuilds on read. Postgres keeps them in the heap.
| Consequence | InnoDB | PostgreSQL |
|---|---|---|
| PK choice impact | Severe — key order is physical order | Mild — heap insert order is independent |
| Secondary index size | Inflated by PK width | Fixed-size tuple pointer |
| UPDATE cost | In-place; old version to undo | New tuple; all indexes updated unless HOT applies |
| Reading old versions | Costs a chain walk | Same cost as current |
| Defining ops problem | Undo history under long transactions | Bloat and transaction id wraparound |
| PK range scan | Excellent — rows are physically adjacent | Good, but heap access may be scattered |
Where Postgres is genuinely ahead
- The optimizer. Merge join, parallel query, better statistics including multivariate extended statistics, and generally sounder plan choices.
- Types and extensibility. JSONB with GIN indexing, arrays, ranges, custom types and operators, and pluggable index access methods — which is how PostGIS and pgvector exist at all.
- One WAL. No dual-log XA overhead on every commit.
- Correctness defaults. Stricter behaviour historically; MySQL only closed much of that gap with 5.7's strict mode.
- CTEs and window functions arrived a decade earlier and are more mature.
Where MySQL is genuinely ahead
- Operations at scale. The ecosystem — Vitess, ProxySQL, gh-ost, Orchestrator, XtraBackup — is more mature for horizontal scale and online change than the Postgres equivalents.
- Replication ergonomics. GTID-based failover is simpler than managing Postgres replication slots, and logical replication arrived in Postgres much later.
- No VACUUM. Postgres's autovacuum tuning and wraparound risk are a genuine, permanent operational burden.
- Clustered locality. When access is primary-key-ordered — multi-tenant data keyed by tenant, time-ordered events — the clustered index is a real, structural win.
- Connection cost. Threads are cheaper than processes, so MySQL tolerates more direct connections before a pooler is mandatory.
What signals depth is not the verdict but the derivation. Anyone can list features; deriving the behaviour from the storage layout is the thing few candidates do.
Where MySQL is going
The release model changed in 2023 and it matters for what you run.
| Line | Support | Run it? |
|---|---|---|
| 8.0 | Extended support through 2026 | Still the most deployed. Fine, but plan the move. |
| 8.4 LTS | Long-term, 8 years | The target. Everything in this module assumes it. |
| 9.x innovation | Short — superseded quarterly | No, not in production. Watch for what lands in the next LTS. |
Recent and incoming: a vector type with distance functions for embedding workloads (9.x); JavaScript stored programs (Enterprise); continued optimizer work on hash join and histograms; and ongoing HeatWave integration on Oracle Cloud, which is a separate analytics engine rather than a change to InnoDB.
You have finished the module
121 chapters, from Monty's ISAM hack in 1994 to a storage engine you wrote yourself. What you should now be able to do, concretely:
- Explain any MySQL behaviour by deriving it from page layout, the B+tree, or the storage engine boundary — rather than recalling a rule.
- Diagnose the four incident classes that account for most MySQL outages: MDL queues, long transactions, checkpoint stalls, and per-connection memory.
- Read a deadlock, an
EXPLAIN ANALYZEtree, and an optimizer trace, and say precisely what each is telling you. - Argue MySQL versus Postgres from mechanism, in both directions.
- Point at a B+tree implementation you wrote, that splits correctly and
survives
kill -9.
The SQL module is the natural next step — it takes the language itself to the same depth, and its execution chapters connect directly back to Part 8.