mysql 执行时间过长排查

mysql 执行时间过长排查

无咎 50 2024-08-05

最初发现是因为项目日志报错:数据库连接超时/被锁。

之后使用 top 命令查看发现,执行时 mysqld 竟然跑满了一整个单核的CPU,但另一个核却几乎完全空闲。因为服务器是双核,故此怀疑是配置文件问题导致 mysqld 无法充分利用可用资源。但更改配置文件后仍然只使用单核,于是打算先从执行的命令上手排查。

添加 慢查询 日志

nano /etc/mysql/mysql.conf.d ,添加如下配置

slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2
log_queries_not_using_indexes = 1

之后使用 systemctl restart mysql 重启使其生效。

通过慢查询日志发现问题:

一条 delete 语句竟然执行了 50s,一条 update 甚至能执行 80s

缓慢原因

delete 语句使用 not in 条件删除中使用子查询会极大拖慢速度,最简单的解决方案就是建立临时表,使用空间换时间的方法。

update 语句的批量更新是循环一条一条的更新记录,一条记录update一次。这样性能很差,也很容易造成阻塞。

解决方案

DELETE FROM table1 WHERE id NOT IN (SELECT * FROM (SELECT MIN(id) AS min_id FROM table1 GROUP BY apk_time, tid, raw_data) temp)

在子查询外层再套一遍,实现简易的建立临时表的方案。

update 语句直接舍弃批量更新,在业务逻辑中逐条更新即可。

最终效果

delete 语句降到 0.06s,总体业务逻辑耗时从 120s 骤减到 3s 之内。