Written By ROMAN AGABEKOV | JUL 05, 2023
Last updated | OCT 11, 2026
Measure | What it tells you |
Application response time, including p95 where available | Whether users are experiencing slow requests |
Requests, transactions, or queries per second | How much work the system is handling |
Errors and connection failures | Whether the slowdown is accompanied by failed work |
CPU, available memory, and swap activity | Whether host resources are constrained |
Storage latency and read/write activity | Whether I/O is part of the bottleneck |
Replication lag, where applicable | Whether a change affects replicas as well as the primary |
SELECT VERSION(), CURRENT_TIMESTAMP(), @@session.time_zone;
SHOW GLOBAL STATUS LIKE 'Uptime'; SELECT SCHEMA_NAME,
DIGEST,
DIGEST_TEXT,
COUNT_STAR,
ROUND(SUM_TIMER_WAIT / 1000000000000, 2) AS total_seconds,
ROUND(AVG_TIMER_WAIT / 1000000000, 2) AS average_ms,
SUM_ROWS_EXAMINED,
SUM_ROWS_SENT,
SUM_CREATED_TMP_DISK_TABLES
FROM performance_schema.events_statements_summary_by_digest
WHERE DIGEST IS NOT NULL
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10; Finding | Investigate first |
One query pattern dominates statement time | Its plan, access pattern, and indexes |
Requests wait on blocked transactions | Lock contention, transaction duration, and application behavior |
Connection failures or repeated connection creation | Application pools, concurrency, and connection settings |
Broad read latency with physical reads | Buffer pool, working set, and storage |
Write latency during heavy updates | Write workload, checkpoint activity, log buffering, and storage |
Expensive sorting or temporary work | Query shape, intermediate results, and engine-specific limits |
Tool or workflow | Best suited to | How to use the result |
MySQLTuner report | An initial review of server configuration and status | Turn recommendations into questions about your workload, memory, and current settings |
Analyzing query workload from available logs | Prioritize query patterns for plan and index review | |
Ongoing monitoring, configuration recommendations, and query analysis | Connect observed workload to changes and keep checking performance afterward |
SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW GLOBAL STATUS
WHERE Variable_name IN (
'Innodb_buffer_pool_read_requests',
'Innodb_buffer_pool_reads'
); Setting | Purpose | Evidence to connect to it |
innodb_buffer_pool_size | InnoDB data and index page cache | Working set, read activity, memory availability, and I/O |
innodb_redo_log_capacity | Disk space available to redo logs | Write workload and checkpoint/flush behavior |
innodb_log_buffer_size | Memory used to buffer redo before it is written | Log-buffer waits in the relevant workload window |
SHOW GLOBAL VARIABLES LIKE 'max_connections';
SHOW GLOBAL STATUS
WHERE Variable_name IN (
'Threads_connected',
'Threads_running',
'Max_used_connections',
'Connection_errors_max_connections'
); SHOW GLOBAL VARIABLES
WHERE Variable_name IN ('thread_handling', 'thread_cache_size');
SHOW GLOBAL STATUS
WHERE Variable_name IN (
'Connections',
'Threads_created',
'Threads_cached'
); SHOW GLOBAL VARIABLES LIKE 'table_open_cache';
SHOW GLOBAL STATUS
WHERE Variable_name IN (
'Open_tables',
'Opened_tables',
'Table_open_cache_hits',
'Table_open_cache_misses',
'Table_open_cache_overflows'
); SHOW GLOBAL STATUS
WHERE Variable_name IN (
'Created_tmp_tables',
'Created_tmp_disk_tables',
'Sort_merge_passes',
'Innodb_log_waits'
); Method | What it changes |
SET SESSION | The current connection's session value, where supported |
SET GLOBAL | The global runtime value; it does not save that change for restart |
SET PERSIST | The global runtime value and a persisted setting in mysqld-auto.cnf |
SET PERSIST_ONLY | A persisted setting without changing the current runtime value |
SELECT @@GLOBAL.thread_cache_size AS current_thread_cache_size;
SELECT VARIABLE_SOURCE, VARIABLE_PATH
FROM performance_schema.variables_info
WHERE VARIABLE_NAME = 'thread_cache_size';
SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM performance_schema.persisted_variables
WHERE VARIABLE_NAME = 'thread_cache_size'; SET GLOBAL thread_cache_size = 32;
SELECT @@GLOBAL.thread_cache_size AS current_thread_cache_size; SET GLOBAL thread_cache_size = 8;
SELECT @@GLOBAL.thread_cache_size AS current_thread_cache_size; SET PERSIST thread_cache_size = 32; SET GLOBAL thread_cache_size = 8;
RESET PERSIST IF EXISTS thread_cache_size; Result | Next action |
The target problem improves without a harmful trade-off | Keep the change, record it, and continue monitoring |
The relevant measurements do not improve | Revisit the hypothesis before adding more changes |
Errors, instability, or resource pressure increase | Follow the recorded recovery procedure and verify restoration |
Area | Difference to account for |
InnoDB and MyISAM caching | InnoDB uses the buffer pool for data and index pages. MyISAM's key_buffer_size controls its index cache, while the operating system caches data files |
Redo configuration | MySQL 5.7 and earlier MySQL 8.0 releases do not use the modern innodb_redo_log_capacity workflow |
Configuration persistence | The SET PERSIST workflow in section 7 is not a MySQL 5.7 procedure |
Execution analysis | EXPLAIN ANALYZE is not available in MySQL 5.7 |
Query cache | It existed in MySQL 5.7, but was removed in MySQL 8.0; query_cache_size is not a modern MySQL tuning target |