mysql查询超时怎么办_mysql查询优化排查

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

看到
Lock wait timeout exceeded
,先别急着调大超时

这个错误不是查询慢,而是事务卡在行锁上等太久被 MySQL 主动中断了。典型表现是:某条

UPDATE
DELETE
执行几秒就报错,但单独
SELECT
很快;日志里带
try restarting transaction

先查谁在锁:
SELECT * FROM performance_schema.data_lock_waits;
(MySQL 8.0+)或
SELECT * FROM information_schema.INNODB_TRX;
+
INNODB_LOCKS
(5.7)
重点看
trx_mysql_thread_id
trx_state
,找出长时间
RUNNING
LOCK WAIT
的线程
别直接
KILL
生产事务——先确认它是不是业务关键操作;更稳妥的是加监控表,用 Event 定期落库锁等待上下文
常见诱因:未提交的事务、长事务里混了
SLEEP()
、应用端没设
transaction timeout
、批量更新没分页

EXPLAIN
显示
type=ALL
?那不是超时,是根本没走索引

很多所谓“查询超时”,其实是执行计划崩了——全表扫描百万行,自然卡死。别一上来就改

wait_timeout
max_execution_time
,先看优化空间。

rows
值远大于实际结果集?说明索引没生效或选错了;检查
key
列是否为
NULL
WHERE 条件字段类型和参数不一致(比如
VARCHAR
字段传数字),会触发隐式转换,索引直接失效
复合索引顺序很重要:
WHERE a = ? AND b > ? ORDER BY c
,推荐建
INDEX(a, b, c)
,而不是分开三个单列索引
避免在索引列上用函数:
WHERE DATE(create_time) = '2026-01-01'
→ 改成
WHERE create_time >= '2026-01-01' AND create_time 

慢查询日志开了,但日志里全是
SELECT 1
?那是连接池健康检查刷屏

这说明你配置的

long_query_time
太低,或者没过滤掉无意义的探测语句,真正慢的业务 SQL 反而被淹没。

确认是否启用了
log_queries_not_using_indexes
——关掉它,否则索引缺失的
SELECT 1
也会进慢日志
生产建议设
long_query_time = 1.0
(不是 0.1),再配合
min_examined_row_limit = 1000
过滤低价值扫描
pt-query-digest /var/log/mysql/slow.log --filter '$event->{Bytes} > 1024'
排除小结果集干扰
别只看
mysqldumpslow -s t
(按时间排序),更要跑
pt-query-digest --report-format profile
看哪类查询占 CPU 最多

HikariCP 报
Communications link failure
?MySQL 没断网,是它自己“踢人”了

这不是网络问题,是 MySQL 服务端主动关闭了空闲连接,而连接池没及时发现并剔除——下一次请求拿了个已断的连接去发 SQL,才爆这个错。

必须同步调大 MySQL 的两个超时:
wait_timeout
interactive_timeout
,只改一个无效(JDBC 初始化时按协议类型选其一)
代码侧比调参更可靠:开 HikariCP 的
validation-timeout=3000
+
max-lifetime=1800000
(30 分钟强制换新连接)
禁用
autoReconnect=true
——MySQL 5.5+ 已废弃,且会掩盖连接泄漏,让问题延迟暴露
Docker 环境改配置别忘挂载:
-v /host/my.cnf:/etc/mysql/conf.d/custom.cnf
,改完必须
docker restart mysql
,reload 不生效

真正难处理的从来不是单一超时参数,而是多个机制叠加失效:MySQL 踢了连接,连接池没检测,应用又没重试逻辑,最后堆栈里只留一句模糊的 “Connection reset”。排查时一定从错误信息里的关键词出发,别凭感觉调参。

相关推荐