一、MySQL 故障快速定位(5 分钟定位根因)
1. 先看整体状态(最关键)
sql
-- 查看 MySQL 整体运行状态
SHOW STATUS;
-- 精简版:只看关键指标
SHOW STATUS LIKE '%Threads%';
SHOW STATUS LIKE '%Queries%';
SHOW STATUS LIKE '%Slow%';
重点看 3 个值:
Threads_connected:当前连接数(太高 = 连接爆了)Threads_running:正在执行的查询数(>10 基本就堵了)Slow_queries:慢查询数量(>0 说明有慢 SQL)
2. 查看正在执行的 SQL(定位卡死 / 慢查询)
sql
-- 查看所有正在跑的查询(含执行时间)
SHOW FULL PROCESSLIST;
-- 更精准:只看运行超过 1 秒的活跃 SQL
SELECT * FROM information_schema.processlist WHERE time > 1 AND command != 'Sleep';
看到这些直接判定故障:
- Sending data:SQL 没索引,全表扫描
- Copying to tmp table:临时表太大,内存不够
- Locked / Waiting for table metadata lock:表被锁死
- Sleep 大量连接:代码没关闭连接,连接池泄露
3. 查看慢查询日志(必开!)
sql
-- 临时开启慢查询(重启失效)
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1; -- 超过 1 秒就算慢查询
SET GLOBAL log_queries_not_using_indexes = 1; -- 记录没走索引的 SQL
慢查询日志是排查所有性能问题的核心。
4. 查看锁等待(表卡死、更新失败)
sql
-- 查看 InnoDB 锁等待
SELECT * FROM information_schema.innodb_locks;
SELECT * FROM information_schema.innodb_lock_waits;
常见锁问题:
- 长事务不提交 → 锁不释放
- 无索引更新 → 行锁变表锁
- DDL(alter table)→ 整表元数据锁死
5. 查看主从延迟(主从同步故障)
sql
SHOW SLAVE STATUS\G
看两个字段:
Seconds_Behind_Master:延迟秒数Slave_SQL_Running: No:SQL 线程挂了(数据冲突 / 权限问题)
二、MySQL 性能优化(从易到难,直接照做)
1. SQL 优化(80% 问题都在这)
① 必做:给 SQL 加索引
sql
-- 查看 SQL 是否走索引
EXPLAIN SELECT * FROM user WHERE phone = '13800138000';
看到 type = ALL 就是全表扫描,必须加索引:
sql
CREATE INDEX idx_phone ON user(phone);
② 禁止这些烂 SQL
SELECT *LIKE '%keyword%'左模糊(不走索引)WHERE 1=1无索引条件- 大表
JOIN无索引 ORDER BY / GROUP BY无索引
③ 分页优化
sql
-- 坏:越往后越慢
SELECT * FROM table LIMIT 100000,20;
-- 好:延迟关联,只查主键
SELECT * FROM table t
JOIN (SELECT id FROM table ORDER BY id LIMIT 100000,20) AS tmp
ON t.id = tmp.id;
2. 连接数优化(连接爆、Too many connections)
sql
-- 查看最大连接数
SHOW VARIABLES LIKE 'max_connections';
-- 调整(my.cnf)
max_connections = 2000
wait_timeout = 600
interactive_timeout = 600
原因: 代码连接池没释放、Sleep 连接太多。
3. InnoDB 缓冲池优化(内存优化)
最核心配置:
plaintext
innodb_buffer_pool_size = 物理内存的 50%~70%
- 32G 内存 → 设 20G
- 64G 内存 → 设 40G
作用:把热数据放内存,磁盘 IO 瞬间下降。
4. 临时表 & 排序优化
plaintext
tmp_table_size = 256M
max_heap_table_size = 256M
sort_buffer_size = 2M
join_buffer_size = 2M
避免 Using temporary、Using filesort。
5. 日志优化(减少磁盘 IO)
plaintext
innodb_flush_log_at_trx_commit = 2 (主从架构推荐)
sync_binlog = 1000
能大幅降低磁盘 IO,提升写入速度。
6. 表结构优化
- 用
INT不用VARCHAR存数字 - 禁止
TEXT/BLOB频繁查询 - 大字段拆表
- 时间用
DATETIME或TIMESTAMP - 尽量用
NOT NULL
三、最常见 6 大故障 + 解决方案
1. CPU 100%
原因: 无索引 SQL、大量排序、全表扫描解决:
SHOW FULL PROCESSLIST找到慢 SQLEXPLAIN加索引- 杀掉烂 SQL
2. 连接数爆了
原因: 代码连接泄露、连接池配置错误解决:
- 杀掉 Sleep 长连接
- 调整
max_connections - 修复应用连接池
3. 磁盘 IO 100%
原因: 缓冲池太小、大量随机 IO、大事务解决:
- 调大
innodb_buffer_pool_size - 优化慢 SQL
- 关闭不必要的日志
4. 表卡死、更新不动
原因: 长事务、MDL 锁、无索引更新解决:
- 查看锁等待
- 杀掉长事务
- 给更新条件加索引
5. 主从延迟巨大
原因: 从库单线程回放、大事务、无索引解决:
- 开启并行复制
- 拆大事务
- 从库也加索引
6. MySQL 突然宕机
原因: OOM、磁盘满、断电解决:
- 看系统日志
/var/log/messages - 看 MySQL 错误日志
error.log - 检查磁盘空间
df -h
四、企业级巡检命令(直接复制用)
sql
-- 1. 查看活跃连接
SHOW FULL PROCESSLIST;
-- 2. 查看慢查询数量
SHOW STATUS LIKE 'Slow_queries';
-- 3. 查看 InnoDB 状态
SHOW ENGINE INNODB STATUS;
-- 4. 查看缓存命中率(>95% 正常)
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';
-- 5. 查看表锁 contention
SHOW STATUS LIKE 'Table_locks%';
五、最佳实践总结
- 慢查询日志必须永久开启
- 所有查询必须走索引
- 禁止长事务(<5 秒)