MySQL 慢查詢排查的實(shí)現(xiàn)
這是一套可直接上手的排查方案,從發(fā)現(xiàn)問題到定位根因,再到優(yōu)化落地,覆蓋全鏈路。
第一步:確認(rèn)慢查詢是否存在
1.1 開啟慢查詢?nèi)罩?/h3>
-- 查看當(dāng)前狀態(tài)
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
-- 臨時開啟(重啟失效)
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1; -- 超過1秒記錄
SET GLOBAL log_queries_not_using_indexes = ON;
-- 查看當(dāng)前狀態(tài) SHOW VARIABLES LIKE 'slow_query%'; SHOW VARIABLES LIKE 'long_query_time'; -- 臨時開啟(重啟失效) SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 1; -- 超過1秒記錄 SET GLOBAL log_queries_not_using_indexes = ON;
1.2 查看慢查詢數(shù)量與內(nèi)容
# 統(tǒng)計慢查詢次數(shù) SHOW GLOBAL STATUS LIKE '%Slow_queries%'; # 查看最近慢查詢?nèi)罩疚募窂? SHOW VARIABLES LIKE 'slow_query_log_file';
第二步:分析慢查詢語句
2.1 使用 EXPLAIN 分析執(zhí)行計劃
EXPLAIN SELECT * FROM orders WHERE status = 1 ORDER BY created_at DESC LIMIT 100;
重點(diǎn)關(guān)注字段:
| 字段 | 危險信號 |
|---|---|
| type | ALL(全表掃描)、index(索引全掃) |
| rows | 遠(yuǎn)大于預(yù)期返回行數(shù) |
| Extra | Using filesort(文件排序)、Using temporary(臨時表) |
2.2 使用 SHOW PROFILE 查看耗時分布
-- 開啟 profiling SET profiling = 1; -- 執(zhí)行你的慢查詢 SELECT * FROM orders WHERE ...; -- 查看所有查詢的耗時 SHOW PROFILES; -- 查看具體某個 Query_ID 的詳細(xì)耗時 SHOW PROFILE FOR QUERY 1;
關(guān)鍵看 Sending data、Sorting result、Creating tmp table 等步驟的耗時占比。
第三步:常見原因與對應(yīng)解決方案
3.1 沒走索引 → 加索引
-- 檢查是否有可用索引 SHOW INDEX FROM orders; -- 添加復(fù)合索引(注意字段順序:等值條件在前,范圍條件在后) ALTER TABLE orders ADD INDEX idx_status_created (status, created_at);
3.2 索引失效 → 改寫 SQL
常見導(dǎo)致索引失效的操作:
- 對索引列使用函數(shù):WHERE DATE(created_at) = '2024-01-01'
- 隱式類型轉(zhuǎn)換:WHERE user_id = '123'(user_id 是 int)
- 前導(dǎo)模糊匹配:WHERE name LIKE '%張三'
3.3 數(shù)據(jù)量過大 → 分頁優(yōu)化 / 歸檔
深分頁優(yōu)化示例:
-- 原始寫法(越往后越慢) SELECT * FROM orders ORDER BY id LIMIT 100000, 20; -- 優(yōu)化寫法(子查詢用覆蓋索引) SELECT * FROM orders WHERE id > (SELECT id FROM orders ORDER BY id LIMIT 100000, 1) ORDER BY id LIMIT 20;
數(shù)據(jù)歸檔: ? 將歷史數(shù)據(jù)遷移到歸檔表或分區(qū)表。
3.4 鎖等待 → 排查鎖沖突
-- 查看當(dāng)前正在等待鎖的事務(wù) SELECT * FROM information_schema.INNODB_TRX\G -- 查看鎖等待關(guān)系 SELECT * FROM sys.schema_table_lock_waits; -- 強(qiáng)制結(jié)束阻塞事務(wù)(慎用) KILL [trx_mysql_thread_id];
3.5 SQL 寫得爛 → 重寫
典型壞寫法:
SELECT *→ 只取需要的列- 子查詢嵌套過深 → 改用 JOIN 或臨時表
OR條件 → 拆成 UNION ALL- 循環(huán)查詢 → 批量查詢 + IN
第四步:系統(tǒng)層面排查
4.1 查看數(shù)據(jù)庫配置是否合理
-- 關(guān)鍵參數(shù)檢查 SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; -- 建議設(shè)為內(nèi)存的60%-70% SHOW VARIABLES LIKE 'tmp_table_size'; -- 臨時表大小限制 SHOW VARIABLES LIKE 'max_connections'; -- 連接數(shù)是否過高
4.2 查看服務(wù)器資源
# CPU、內(nèi)存、IO 情況 top iostat -x 1 free -h
如果 CPU 高但 IO 低 → SQL 計算量大或索引不合理
如果 IO 高但 CPU 低 → 磁盤瓶頸,考慮 SSD 或增加 buffer pool
第五步:建立長效機(jī)制
5.1 定期巡檢腳本
-- 查詢當(dāng)前運(yùn)行時間最長的SQL SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep' ORDER BY TIME DESC LIMIT 10; -- 查詢?nèi)頀呙璐螖?shù)最多的表 SELECT * FROM sys.schema_unused_indexes;
5.2 監(jiān)控告警
- 設(shè)置
long_query_time = 1,持續(xù)采集慢查詢?nèi)罩?/li> - 使用 Percona Toolkit 的
pt-query-digest分析日志規(guī)律 - 接入 Prometheus + Grafana 監(jiān)控 QPS、慢查詢數(shù)量趨勢
一句話總結(jié)排查思路
先確認(rèn)慢在哪(日志+profile),再看為什么慢(explain+索引),最后對癥下藥(加索引/改SQL/擴(kuò)資源)。
到此這篇關(guān)于MySQL 慢查詢排查的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)MySQL 慢查詢排查內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL數(shù)據(jù)庫健康檢查從腳本到全面巡檢的完整方案
在數(shù)據(jù)庫運(yùn)維工作中,定期對MySQL數(shù)據(jù)庫進(jìn)行健康檢查是保證系統(tǒng)穩(wěn)定運(yùn)行的重要環(huán)節(jié),一個完善的數(shù)據(jù)庫巡檢方案可以幫助DBA及時發(fā)現(xiàn)潛在問題,優(yōu)化性能,預(yù)防故障發(fā)生,本文將基于多個優(yōu)秀的MySQL巡檢腳本實(shí)現(xiàn),整理出一套完整的MySQL健康檢查方案,需要的朋友可以參考下2025-11-11
mysql正確安全清空在線慢查詢?nèi)罩緎low log的流程分享
這篇文章主要介紹了正確安全清空在線慢查詢?nèi)罩緎low log的流程,需要的朋友可以參考下2014-02-02
MySQL線程處于Opening tables的問題解決方法
在本篇文章里小編給大家分享了關(guān)于MySQL線程處于Opening tables的問題解決方法,有興趣的朋友們學(xué)習(xí)下。2019-01-01
如何解決mysql出現(xiàn)Incorrect string value for co
這篇文章主要介紹了如何解決mysql出現(xiàn)Incorrect string value for column ‘表項(xiàng)‘ at row 1錯誤問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-03-03
Mysql錯誤1366 - Incorrect integer value解決方法
這篇文章主要介紹了Mysql錯誤1366 - Incorrect integer value解決方法,本文通過修改字段默認(rèn)值解決,需要的朋友可以參考下2014-09-09

