Every MySQL shop starts with mysqldump because it is already installed, and most keep it long past the point where it stopped being the right tool. I know because I have been the person watching a "nightly" dump finish at 11 a.m. These are field notes on where mysqldump breaks down, what mydumper and myloader actually change, and the boundary where you should stop using logical backups entirely.
The framing matters: dump time is annoying, restore time is existential. Judge every option in this post by how long it takes to get a working server back, not by how long the backup takes to write.
Where mysqldump stops scaling
mysqldump is single-threaded on one connection. It walks tables sequentially, serializes rows to SQL text, and produces one stream. With the right flags it is perfectly correct for InnoDB: the flag that matters is single-transaction, which opens a consistent snapshot under REPEATABLE READ so the dump reflects one moment in time without locking writers out.
Correct is not the same as scalable. One thread means dump duration grows with data size, full stop, and the long-lived snapshot transaction has its own cost: for the entire dump, InnoDB must retain undo history so the snapshot can keep seeing old row versions while other sessions change them. On a busy write workload, a multi-hour dump means hours of history-list growth and purge lag. The restore is worse: a mysqldump stream replays through one connection, one statement at a time, rebuilding every secondary index as it goes.
Before choosing tooling, know what you are actually dumping. Size and shape drive everything downstream.
SELECT table_schema,
COUNT(*) AS tables,
ROUND(SUM(data_length) / 1024 / 1024 / 1024, 1) AS data_gb,
ROUND(SUM(index_length) / 1024 / 1024 / 1024, 1) AS index_gb
FROM information_schema.tables
WHERE table_schema NOT IN ('mysql', 'sys', 'performance_schema', 'information_schema')
GROUP BY table_schema
ORDER BY data_gb DESC;
My rule of thumb is unscientific but has served me well: once a straight mysqldump cannot finish comfortably inside your quietest window, stop tuning flags and change tools. One footnote while you evaluate: mysqlpump, the parallel dump tool that shipped with the server, was deprecated during 8.0 and removed in MySQL 8.4, so do not build anything new on it.
What mydumper changes
mydumper attacks both axes. It dumps with multiple threads, writes one file per table, and can split large tables into chunks with the rows option so a single giant table does not serialize the run. Per-table files alone justify the migration: selective restore of one table no longer means carving up a 400 GB SQL stream.
The interesting engineering is in consistency. Parallel connections do not naturally see the same snapshot, so mydumper coordinates them: it briefly quiesces writes, classically with FLUSH TABLES WITH READ LOCK, while every worker opens its transaction and the binlog coordinates are captured, then releases the lock and lets the workers dump their consistent snapshots in parallel. The metadata file it writes records the binlog file, position, and GTID set, which is exactly what you need to attach the restored copy as a replica or start binlog replay from it.
That brief global lock is the sharp edge. FLUSH TABLES WITH READ LOCK must wait for every running statement to finish, and while it waits, everything else queues behind it. A ten-minute analytics query at the wrong moment turns a sub-second lock into a ten-minute outage. Check for long-running transactions before the dump starts, and abort if you find any.
SELECT trx_id,
trx_started,
TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS seconds_open,
trx_rows_modified,
LEFT(trx_query, 120) AS current_query
FROM information_schema.innodb_trx
ORDER BY trx_started
LIMIT 10;
mydumper offers softer options for setups that cannot tolerate the lock at all, but each one trades away a guarantee, usually snapshot coverage for non-InnoDB tables or exact coordinate capture. Read the flags you enable; "the dump got faster" is sometimes a symptom of "the dump got weaker."
Two practical notes that save disk and transfer time at scale: mydumper compresses per-file as it writes, which parallelizes the compression work along with the dump instead of leaving you gzipping a giant artifact afterwards, and per-table files ship to object storage incrementally rather than as one monolithic upload at the end. On a dump measured in hundreds of gigabytes, when the artifact becomes durable matters almost as much as when the dump finishes.
Restore is the real benchmark
myloader restores in parallel across tables, which is where the wall-clock win over a mysqldump replay usually comes from on multi-table schemas. The limiting factor becomes InnoDB itself: secondary indexes get rebuilt during load, redo has to absorb the write burst, and a single monster table still bottlenecks on its own indexes no matter how many threads you configure.
The standard restore-side moves: disable binary logging on the target if nothing replicates from it, relax durability for the duration of the load (innodb_flush_log_at_trx_commit set to 0 or 2) and restore it afterwards, and defer secondary index creation until the data is in, which mydumper and myloader can orchestrate with the innodb-optimize-keys option. Every one of those is a deliberate, temporary trade of safety for speed on a disposable target; write them into the runbook explicitly so nobody leaves durability relaxed on a server that gets promoted.
Also give MySQL Shell's dump utilities a fair look before standardizing. util.dumpInstance and util.loadDump are Oracle-maintained, parallel, chunked, compressed, and defer secondary index creation by default; for cloud migrations they have become the path of least resistance, and they solve the same problems mydumper does with different ergonomics.
Whatever loads the data, verify the result like you mean it. A restore that "completed without errors" has proven only that the SQL parsed. My minimum bar: compare per-schema table counts and sizes against the source, run exact row counts on a handful of business-critical tables, confirm the binlog coordinates from the dump metadata let the restored copy attach as a replica and converge, and run one real application query. A logical pipeline has more steps than a physical one, and every step is a place where a table can silently go missing from the file list.
When logical beats physical
I keep both logical and physical pipelines, because they answer different questions. Logical wins when the data must change shape in transit: major-version upgrades where you want a clean rebuild, cross-platform moves, schema surgery, extracting one tenant or one table, escaping page-level corruption that a physical copy would faithfully reproduce, and feeding non-MySQL targets. A SQL-text artifact is also the most auditable backup there is.
Logical absolutely does not win on restore time at scale. Replaying SQL and rebuilding indexes for a multi-terabyte instance takes many hours or days, and no thread count fully fixes that; a prepared physical backup comes back at file-copy speed. Physical backups plus binary logs are also the only serious point-in-time recovery base. I walked through that pairing, and how the whole model compares to PostgreSQL's pg_dump versus base-backup split, in MySQL backups vs PostgreSQL backups.
The cadence that has worked for me on large systems: physical backups plus binlogs as the recovery spine, run daily or better, and a logical dump weekly or on demand as the escape hatch and migration artifact. The logical job runs against a replica so its snapshot transaction ages someone else's undo history, and its restore drill happens on the same schedule as the physical one. Neither pipeline is optional; they fail differently, which is the point.
Monitor the pipeline, not just the cron job
Whichever tool wins, the backup job is a production workload with observable side effects: snapshot transactions that age for hours, history list length growth during long dumps, the FTWRL stall window, disk pressure from dump output, and restore rehearsal durations that quietly grow with the dataset. Alert on backup age and verified success, record restore drill times as first-class metrics, and watch the donor's transaction behavior during every dump window. If you run mixed fleets, the MySQL to PostgreSQL monitoring translation notes map these signals to their Postgres equivalents.
Where MonPG fits today
Straight positioning: MonPG is a PostgreSQL monitoring platform and does not monitor MySQL today. We are building MySQL monitoring (coming soon), and backup-window visibility, long-open snapshot transactions, history list growth, lock stalls behind FTWRL, is on the roadmap precisely because these failure modes are invisible in generic host metrics. If PostgreSQL is also part of your fleet, that side ships today and you can start there. Until the MySQL side lands, the practical takeaways stand alone: parallelize the dump, rehearse the restore, and never let a logical backup be your only way home.