MySQL中慢查詢排查的完整流程詳解
這是一套可直接上手的排查方案,從發(fā)現(xiàn)問題到定位根因,再到優(yōu)化落地,覆蓋全鏈路。
第一步:確認慢查詢是否存在
1.1 開啟慢查詢?nèi)罩?/h3>
-- 查看當前狀態(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;
-- 查看當前狀態(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;
重點關注字段:
| 字段 | 危險信號 |
|---|---|
type | ALL(全表掃描)、index(索引全掃) |
rows | 遠大于預期返回行數(shù) |
Extra | Using filesort(文件排序)、Using temporary(臨時表) |
2.2 使用 SHOW PROFILE 查看耗時分布
-- 開啟 profiling SET profiling = 1; -- 執(zhí)行你的慢查詢 SELECT * FROM orders WHERE ...; -- 查看所有查詢的耗時 SHOW PROFILES; -- 查看具體某個 Query_ID 的詳細耗時 SHOW PROFILE FOR QUERY 1;
關鍵看 Sending data、Sorting result、Creating tmp table 等步驟的耗時占比。
第三步:常見原因與對應解決方案
3.1 沒走索引 → 加索引
-- 檢查是否有可用索引 SHOW INDEX FROM orders; -- 添加復合索引(注意字段順序:等值條件在前,范圍條件在后) ALTER TABLE orders ADD INDEX idx_status_created (status, created_at);
3.2 索引失效 → 改寫 SQL
常見導致索引失效的操作:
- 對索引列使用函數(shù):
WHERE DATE(created_at) = '2024-01-01' - 隱式類型轉換:
WHERE user_id = '123'(user_id 是 int) - 前導模糊匹配:
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 鎖等待 → 排查鎖沖突
-- 查看當前正在等待鎖的事務 SELECT * FROM information_schema.INNODB_TRX\G -- 查看鎖等待關系 SELECT * FROM sys.schema_table_lock_waits; -- 強制結束阻塞事務(慎用) KILL [trx_mysql_thread_id];
3.5 SQL 寫得爛 → 重寫
典型壞寫法:
SELECT *→ 只取需要的列- 子查詢嵌套過深 → 改用 JOIN 或臨時表
OR條件 → 拆成 UNION ALL- 循環(huán)查詢 → 批量查詢 + IN
第四步:系統(tǒng)層面排查
4.1 查看數(shù)據(jù)庫配置是否合理
-- 關鍵參數(shù)檢查 SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; -- 建議設為內(nèi)存的60%-70% SHOW VARIABLES LIKE 'tmp_table_size'; -- 臨時表大小限制 SHOW VARIABLES LIKE 'max_connections'; -- 連接數(shù)是否過高
4.2 查看服務器資源
# CPU、內(nèi)存、IO 情況 top iostat -x 1 free -h
如果 CPU 高但 IO 低 → SQL 計算量大或索引不合理
如果 IO 高但 CPU 低 → 磁盤瓶頸,考慮 SSD 或增加 buffer pool
第五步:建立長效機制
5.1 定期巡檢腳本
-- 查詢當前運行時間最長的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)控告警
- 設置
long_query_time = 1,持續(xù)采集慢查詢?nèi)罩?/li> - 使用 Percona Toolkit 的
pt-query-digest分析日志規(guī)律 - 接入 Prometheus + Grafana 監(jiān)控 QPS、慢查詢數(shù)量趨勢
一句話總結排查思路
先確認慢在哪(日志+profile),再看為什么慢(explain+索引),最后對癥下藥(加索引/改SQL/擴資源)。
到此這篇關于MySQL中慢查詢排查的完整流程詳解的文章就介紹到這了,更多相關MySQL慢查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
MySQL 權限撤銷(REVOKE)機制:從語法到安全實踐指南
在MySQL的用戶權限管理體系中,REVOKE語句是用于撤銷已授予用戶的特定權限的核心命令,本文將圍繞REVOKE的語法規(guī)范、權限作用域、常見誤區(qū)及安全最佳實踐展開深入解析,感興趣的朋友跟隨小編一起看看吧2026-06-06
解決Navicat for Mysql連接報錯1251的問題(連接失敗)
記得在之前給大家介紹過Navicat for Mysql連接報錯的問題,可能寫的不夠詳細,今天在稍作修改補充下,對Navicat for Mysql連接報錯1251問題感興趣的朋友跟隨小編一起看看吧2021-05-05
MySQL中distinct語句去查詢重復記錄及相關的性能討論
這篇文章主要介紹了MySQL中distinct語句去查詢重復記錄及相關的性能討論,文中的觀點是在一定情況下避免在最高層查詢中使用distinct,需要的朋友可以參考下2016-01-01
MySQL數(shù)據(jù)庫誤刪數(shù)據(jù)該怎么解決(這里有救!)
在日常運維工作中,對于mysql數(shù)據(jù)庫的備份是至關重要的,下面這篇文章主要介紹了MySQL數(shù)據(jù)庫誤刪數(shù)據(jù)該怎么解決的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2025-09-09

