MySQL Monitoring: The Complete 2026 Guide
Monitor MySQL like an SRE — the 15 metrics that matter, slow query log setup, replication lag alerts, connection pool traps, and exporter configs.
Short answer: Effective MySQL monitoring rests on four pillars: availability (can you connect and execute?), performance (query latency, slow log, buffer pool hit ratio), saturation (connections, threads, disk), and replication (lag, thread status). Instrument with mysqld_exporter for metrics plus the slow query log and performance_schema for query-level detail; alert on connection exhaustion, replication lag, and buffer pool misses before they page your users. Every metric, query, and alert rule below is production-tested and copy-paste ready (MySQL 8.x / 8.4 LTS).
The 15 metrics that actually matter
| Metric | Source | Watch for | Alert sketch |
|---|---|---|---|
mysql_up |
exporter | 0 = down | page immediately |
| Connections used % | max_used_connections / max_connections |
> 80% | page at 90% |
| Threads running | Threads_running |
sustained > vCPU×2 | warning |
| Buffer pool hit ratio | 1 - Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests |
< 99% | investigate |
| Buffer pool dirty pages | Innodb_buffer_pool_pages_dirty |
flush stalls | warning |
| Slow queries rate | Slow_queries delta |
> 1% of questions | warning |
| QPS / TPS | Questions, Com_commit+Com_rollback |
baseline deviations | anomaly |
| Row lock waits | Innodb_row_lock_waits |
spikes | warning |
| Deadlocks | Innodb_deadlocks (8.0.18+) |
any | investigate each |
| Replication lag | Seconds_Behind_Source |
> 30s | page at 60s |
| Replica SQL thread | Replica_SQL_Running |
No | page |
| Disk usage (datadir) | node exporter | < 15% free | page at 10% |
| Binlog disk growth | binlog volume | surprise growth | warning |
| Temp tables on disk | Created_tmp_disk_tables / Created_tmp_tables |
> 25% | tune queries |
| Aborted connects | Aborted_connects |
spikes | auth/network issue |
The slow query log: your highest-ROI instrument
# my.cnf — production-safe defaults
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1 # seconds; start at 1, tighten to 0.2 on hot paths
log_queries_not_using_indexes = 1 # finds the queries indexes forgot
min_examined_row_limit = 1000 # skip trivial scans
Analyze without reading raw logs:
Related guideMySQL Integration→
# Top 10 queries by total time (pt-query-digest)
pt-query-digest /var/log/mysql/slow.log --limit 10 --no-report > /tmp/digest.txt
# Or with mysqldumpslow
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
Rule of thumb: sort by total time (frequency × avg latency), not worst single execution — a 200 ms query running 100K times a day costs more than a 10 s query running twice. Our dedicated slow-query guide walks a full optimization loop with EXPLAIN output.
performance_schema: query detail without an agent
-- Top statements by total latency (sys schema wraps performance_schema)
SELECT digest_text, count_star, round(avg_timer_wait/1e12,2) AS avg_s,
round(sum_timer_wait/1e12,2) AS total_s
FROM sys.statements_with_runtimes_in_95th_percentile
ORDER BY sum_timer_wait DESC LIMIT 10;
-- Who holds locks right now
SELECT * FROM sys.innodb_lock_waits;
-- Full table scans worth indexing
SELECT * FROM sys.statements_with_full_table_scans ORDER BY no_index_used_count DESC LIMIT 10;
performance_schema overhead on modern MySQL is typically 3–7% when fully enabled; the sys schema views above are the safe starting set.
Collection: mysqld_exporter → Prometheus (or direct to platform)
# prometheus.yml
scrape_configs:
- job_name: mysql
static_configs:
- targets: ['db-exporter:9104']
# exporter needs a read-only user
CREATE USER 'exporter'@'%' IDENTIFIED BY '...' WITH MAX_USER_CONNECTIONS 3;
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'%';
Managed platform alternative: Guance's DataKit collects MySQL metrics, slow logs (parsed into structured events), and performance_schema digests in one input config, correlating them with infrastructure and APM data — useful when the database is one tier of a larger stack you're watching in a single console.
Replication: the failure mode everyone forgets to alert on
SHOW REPLICA STATUS\G
-- Watch: Replica_IO_Running, Replica_SQL_Running, Seconds_Behind_Source,
-- Last_Errno / Last_Error (silent drift source)
Alert on three states: SQL thread No (replication broken), lag > 30s (read-your-writes risk for apps reading replicas), and lag flapping (network or write-burst symptom). In Group Replication / InnoDB Cluster setups, also watch member_state and transactions_validating backlog.
Related guideHow to Monitor MySQL Slow Queries: Setup, Analysis, Alerts (2026)→
The 5 failure paths (learn from others' pages)
- Connection exhaustion via pools. App pools × app replicas >
max_connections. The DB dies at 2 a.m. after a deploy tripled replica count. Fix: alert at 80% used, size pools asmax_connections / (replicas + headroom). - Buffer pool miss storm. Working set quietly outgrew
innodb_buffer_pool_size; hit ratio slides from 99.9% to 97% and latency triples. Fix: chart hit ratio weekly; resize or reduce working set. - Replica lag invisible to apps. Reads served stale data for hours because lag wasn't monitored per-replica. Fix: per-replica lag alerts; route reads by measured lag.
- Disk full from binlogs.
binlog_expire_logs_secondsunset on a busy primary. Fix: set expiry, alert on datadir free space. - Lock-wait pileups. One long transaction holds row locks;
Threads_runningclimbs; everything queues. Fix: alert on lock waits; kill policy for transactions > N seconds; keep transactions short.
FAQ
Q: What are the most important MySQL metrics to monitor?
Five cover most incidents: connection usage (max_used_connections/max_connections), InnoDB buffer pool hit ratio, Threads_running, slow query rate, and replication lag/thread status. Add disk free space on the datadir. Everything else is refinement.
Q: How do I monitor MySQL slow queries?
Enable the slow query log (slow_query_log=1, long_query_time=1), then analyze with pt-query-digest sorted by total time. For live detail without log parsing, query sys.statements_with_runtimes_in_95th_percentile (backed by performance_schema). Our slow-query monitoring guide covers the full EXPLAIN-driven optimization loop.
Q: What is a good buffer pool hit ratio?
99% or higher for OLTP workloads. Values sliding toward 95–97% mean the working set is outgrowing innodb_buffer_pool_size — either add RAM or shrink the hot dataset (indexes, archiving). Watch the trend, not the snapshot.
Q: How do I monitor MySQL on Kubernetes?
Run mysqld_exporter as a sidecar or a separate deployment scraping the Service; collect the slow log via a log collector (Fluent Bit/DataKit) from a shared volume; label everything with namespace/pod/cluster. Managed MySQL (RDS/Cloud SQL) instead exposes metrics via the cloud provider — see our RDS monitoring guide.
Q: MySQL monitoring vs observability platforms — when to upgrade?
Exporters + Prometheus + Grafana cover metrics and alerting well. You outgrow the DIY stack when you need slow-log content correlated with traces (which endpoint caused this query), multi-cluster views, or retention beyond local storage — the point where all-in-one platforms (Datadog DBM, Guance, Percona PMM) earn their cost.
Sources: MySQL 8.x/8.4 documentation (performance_schema, sys schema, replication), prometheus mysqld_exporter documentation, Percona pt-query-digest docs. Verified 2026-08-07.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan