mysql高并发下如何控制查询延迟_mysql延迟优化方案

来源:这里教程网 时间:2026-02-28 20:47:58 作者:

为什么
SELECT
在高并发下突然变慢?先看真实瓶颈点

不是所有“慢查询”都该优化 SQL,高并发下

SELECT
延迟飙升,大概率卡在锁、IO 或连接争用上。比如:大量短连接反复建连耗尽
wait_timeout
资源;或二级索引 +
WHERE
条件触发间隙锁,导致后续查询被阻塞;又或者
innodb_buffer_pool_size
设置过小,频繁刷脏页+磁盘随机读。

EXPLAIN
看不准延迟?必须补上
SHOW PROFILE
sys.schema_table_statistics

EXPLAIN
只反映执行计划,不体现真实 IO 和锁等待。高并发场景下更需定位“谁在等什么”:

SHOW PROFILE FOR QUERY N
查看单次查询各阶段耗时(重点关注
Waiting for table metadata lock
Sending data
Creating sort index
sys.schema_table_statistics
找出物理读最多的表:
SELECT * FROM sys.schema_table_statistics WHERE total_latency LIKE '%s%' ORDER BY io_read_latency DESC LIMIT 5
确认是否命中缓冲池:
SELECT (1 - (innodb_buffer_pool_reads / innodb_buffer_pool_read_requests)) * 100 AS hit_rate FROM information_schema.GLOBAL_STATUS WHERE variable_name IN ('innodb_buffer_pool_reads', 'innodb_buffer_pool_read_requests')

加索引反而更慢?注意
WHERE
条件顺序和
IN
列表长度

复合索引失效常发生在高并发写入后统计信息未更新,或

IN
子句超过 MySQL 优化器阈值(默认约 300 项),导致放弃使用索引走全表扫描:

ANALYZE TABLE
强制刷新统计信息(尤其在大批量
INSERT/DELETE
后)
避免
WHERE a = ? AND b IN (?, ?, ..., ?)
b
IN
列表超 200 项;拆成多个查询或改用临时表
JOIN
索引字段顺序要匹配最常用过滤组合,例如高频查
status = 'active' AND created_at > '2024-01-01'
,就建
INDEX(status, created_at)
,而非反过来

连接池配多大才不拖垮 MySQL?关键看
max_connections
wait_timeout
协同

应用层连接池(如 HikariCP)设 100,但 MySQL

max_connections=151
默认值极易打满,且空闲连接不及时释放会持续占用内存和锁资源:

先调高
max_connections
(建议按峰值 QPS × 平均查询耗时 × 1.5 估算,但不超过 OS 文件描述符限制)
wait_timeout
从默认 28800(8 小时)降到 60–300 秒,配合连接池的
idleTimeout
使用
禁止应用代码中手动
CONNECTION.close()
后再复用,MySQL 不支持连接重用,必须由连接池管理生命周期

真正难的是锁竞争与缓冲区争用,这两个问题不会因为加了索引或调了连接数就自动消失——它们藏在慢日志的

Rows_examined
InnoDB_row_lock_waits
指标背后,得盯着看。

相关推荐