一、故障排查概述
1.1 故障排查方法论
python
故障排查流程 = [
"1. 发现问题:监控告警、用户反馈、性能下降",
"2. 收集信息:错误日志、慢查询、系统状态",
"3. 分析定位:确定问题范围、复现条件",
"4. 制定方案:评估影响、选择解决方案",
"5. 执行修复:备份数据、执行操作、验证结果",
"6. 复盘总结:记录原因、优化预防、更新文档"
]
1.2 常用诊断工具
| 工具 | 用途 | 命令示例 |
|---|---|---|
| SHOW PROCESSLIST | 查看当前连接 | SHOW FULL PROCESSLIST; |
| SHOW ENGINE INNODB STATUS | InnoDB状态 | SHOW ENGINE INNODB STATUS\G |
| PERFORMANCE_SCHEMA | 性能监控 | SELECT * FROM sys.schema_table_statistics; |
| pt-query-digest | 慢查询分析 | pt-query-digest slow.log |
| mysqldumpslow | 慢查询摘要 | mysqldumpslow -s t -t 10 slow.log |
| dmesg | 系统日志 | `dmesg |
二、连接问题排查
2.1 无法连接MySQL
bash
# 1. 检查MySQL服务状态
systemctl status mysql
ps aux | grep mysqld
# 2. 检查端口监听
netstat -tlnp | grep 3306
ss -tlnp | grep 3306
# 3. 检查防火墙
iptables -L -n | grep 3306
firewall-cmd --list-all
ufw status
# 4. 检查最大连接数
mysql -u root -p -e "SHOW VARIABLES LIKE 'max_connections';"
mysql -u root -p -e "SHOW STATUS LIKE 'Threads_connected';"
# 5. 检查连接超时设置
mysql -u root -p -e "SHOW VARIABLES LIKE '%timeout%';"
2.2 连接数过多
sql
-- 查看当前连接
SHOW PROCESSLIST;
SHOW FULL PROCESSLIST;
-- 按状态统计连接数
SELECT state, COUNT(*) FROM information_schema.PROCESSLIST GROUP BY state;
-- 按用户统计连接数
SELECT user, COUNT(*) FROM information_schema.PROCESSLIST GROUP BY user;
-- 按主机统计连接数
SELECT SUBSTRING_INDEX(host, ':', 1) AS ip, COUNT(*)
FROM information_schema.PROCESSLIST
GROUP BY ip ORDER BY COUNT(*) DESC;
-- 杀掉特定连接
KILL connection_id;
KILL QUERY connection_id; -- 只杀掉查询,不断开连接
-- 批量杀掉特定IP的连接
SELECT CONCAT('KILL ', id, ';')
FROM information_schema.PROCESSLIST
WHERE host LIKE '192.168.1.100%'
INTO OUTFILE '/tmp/kill.sql';
SOURCE /tmp/kill.sql;
2.3 Too many connections 错误
sql
-- 临时增加最大连接数
SET GLOBAL max_connections = 500;
-- 永久配置(my.cnf)
[mysqld]
max_connections = 500
max_connect_errors = 100000
back_log = 300 # 连接队列大小
-- 减少空闲连接超时
SET GLOBAL wait_timeout = 600;
SET GLOBAL interactive_timeout = 600;
-- 查看连接复用情况
SHOW STATUS LIKE 'Threads%';
-- Threads_cached: 缓存的线程数
-- Threads_connected: 当前连接数
-- Threads_created: 创建的线程数(应尽量接近Threads_connected)
三、性能问题排查
3.1 慢查询分析
sql
-- 1. 开启慢查询日志
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 2; -- 超过2秒记录
SET GLOBAL log_queries_not_using_indexes = ON;
-- 查看慢查询配置
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
-- 2. 查看慢查询数量
SHOW STATUS LIKE 'Slow_queries';
-- 3. 分析当前慢查询
SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 10;
3.2 使用EXPLAIN分析查询
sql
-- EXPLAIN输出字段说明
EXPLAIN SELECT * FROM students WHERE age > 18;
-- 关键字段含义
-- id: 查询执行顺序
-- select_type: 查询类型(SIMPLE/PRIMARY/SUBQUERY/DERIVED/UNION)
-- table: 查询的表
-- type: 访问类型(性能从好到差:system > const > eq_ref > ref > range > index > ALL)
-- possible_keys: 可能使用的索引
-- key: 实际使用的索引
-- key_len: 索引使用的字节数
-- ref: 索引比较的列
-- rows: 预估扫描的行数
-- Extra: 额外信息(Using index/Using where/Using temporary/Using filesort)
-- 详细分析(MySQL 8.0+)
EXPLAIN ANALYZE SELECT * FROM students WHERE age > 18;
3.3 常见慢查询优化
sql
-- 1. 索引失效的情况
-- 避免在索引列上使用函数
-- 坏
SELECT * FROM students WHERE YEAR(created_at) = 2024;
-- 好
SELECT * FROM students WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';
-- 避免隐式类型转换
-- 坏(phone是varchar)
SELECT * FROM students WHERE phone = 13800138000;
-- 好
SELECT * FROM students WHERE phone = '13800138000';
-- 避免使用LIKE以通配符开头
-- 坏
SELECT * FROM students WHERE name LIKE '%三';
-- 好
SELECT * FROM students WHERE name LIKE '张%';
-- 2. 优化分页查询
-- 坏(大偏移量)
SELECT * FROM students ORDER BY id LIMIT 100000, 20;
-- 好(使用游标)
SELECT * FROM students WHERE id > 100000 ORDER BY id LIMIT 20;
-- 3. 优化子查询
-- 坏
SELECT * FROM students WHERE class_id IN (SELECT id FROM classes WHERE grade = '高一');
-- 好
SELECT s.* FROM students s JOIN classes c ON s.class_id = c.id WHERE c.grade = '高一';
-- 4. 优化COUNT查询
-- 坏(统计所有行)
SELECT COUNT(*) FROM students;
-- 好(使用近似值)
SELECT TABLE_ROWS FROM information_schema.tables WHERE table_name = 'students';
3.4 锁问题排查
sql
-- 1. 查看当前锁等待
SELECT * FROM information_schema.INNODB_TRX; -- 当前事务
SELECT * FROM information_schema.INNODB_LOCKS; -- 当前锁
SELECT * FROM information_schema.INNODB_LOCK_WAITS; -- 锁等待关系
-- 2. 查询锁等待详情(MySQL 8.0)
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.data_lock_waits;
-- 3. 查看死锁信息
SHOW ENGINE INNODB STATUS\G
-- 查找 "LATEST DETECTED DEADLOCK" 部分
-- 4. 杀掉阻塞的事务
SELECT trx_mysql_thread_id FROM information_schema.INNODB_TRX
WHERE trx_state = 'RUNNING' AND trx_started < NOW() - INTERVAL 60 SECOND;
-- 5. 查看表锁
SHOW OPEN TABLES WHERE In_use > 0;
-- 6. 查看元数据锁
SELECT * FROM performance_schema.metadata_locks;
四、复制问题排查
4.1 复制延迟
sql
-- 1. 查看复制延迟
SHOW SLAVE STATUS\G
-- 关注字段:Seconds_Behind_Master
-- 2. 查看复制线程状态
SHOW PROCESSLIST;
-- 查看 Slave_IO_Running 和 Slave_SQL_Running 线程
-- 3. 开启并行复制
-- 配置文件中设置
slave_parallel_workers = 4
slave_parallel_type = LOGICAL_CLOCK
-- 动态调整
SET GLOBAL slave_parallel_workers = 4;
STOP SLAVE SQL_THREAD;
START SLAVE SQL_THREAD;
-- 4. 调整从库刷盘策略
SET GLOBAL sync_relay_log = 0;
SET GLOBAL sync_relay_log_info = 0;
-- 5. 查看复制延迟原因
SELECT * FROM performance_schema.replication_applier_status_by_worker\G
4.2 复制中断
sql
-- 1. 查看错误信息
SHOW SLAVE STATUS\G
-- 查看 Last_Errno 和 Last_Error
-- 2. 跳过错误
-- 跳过1个错误
STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
START SLAVE;
-- 3. 使用GTID跳过错误
STOP SLAVE;
SET GTID_NEXT = 'uuid:transaction_id';
BEGIN; COMMIT;
SET GTID_NEXT = 'AUTOMATIC';
START SLAVE;
-- 4. 跳过特定错误(配置文件中)
slave-skip-errors = 1062,1032,1053
-- 5. 重建复制
STOP SLAVE;
RESET SLAVE ALL;
CHANGE MASTER TO ...;
START SLAVE;
4.3 主从数据不一致
bash
# 1. 使用pt-table-checksum检查差异
pt-table-checksum --user=root --password=pass \
--host=192.168.1.100 --databases=school \
--replicate=checksum.checksums
# 2. 使用pt-table-sync修复
pt-table-sync --execute --sync-to-master \
--user=root --password=pass h=192.168.1.101
# 3. 手动修复
# 从主库导出问题表
mysqldump -u root -p school students > students.sql
# 在从库导入
mysql -u root -p school < students.sql