1. 慢查询排查的黄金五步法
当数据库突然变慢时,很多DBA会陷入手忙脚乱的境地。根据我多年处理生产环境数据库性能问题的经验,建议按照以下优先级顺序进行排查:
1.1 当前活跃会话与阻塞分析
首先登录数据库执行:
sql复制-- MySQL
SHOW PROCESSLIST;
-- 或更详细的版本
SELECT * FROM information_schema.processlist WHERE COMMAND != 'Sleep';
-- Oracle
SELECT sid, serial#, username, status, machine, program, sql_id FROM v$session
WHERE status = 'ACTIVE';
重点关注:
Command列显示"Query"或"Execute"的长时间运行会话Time列显示执行时间超过30秒的查询State列出现"Waiting for table lock"等阻塞状态
经验:生产环境中,超过80%的突发性能问题都是由锁等待或会话堆积引起的。我曾遇到一个UPDATE语句没加索引导致全表锁定的案例,阻塞了200多个后续请求。
1.2 实时慢查询捕获
对于没有开启慢查询日志的情况,可以临时抓取当前慢查询:
sql复制-- MySQL 8.0+
SELECT * FROM performance_schema.events_statements_history_long
WHERE TIMER_WAIT > 1000000000 -- 单位皮秒,这里设为1秒
ORDER BY TIMER_WAIT DESC LIMIT 10;
-- PostgreSQL
SELECT pid, now() - query_start AS duration, query
FROM pg_stat_activity
WHERE state = 'active' AND now() - query_start > interval '1 second';
关键指标:
- 执行时间分布(是否突然出现大量1秒以上查询)
- 相同SQL模板出现的频率
- 查询涉及的表是否有重合
1.3 系统资源瓶颈检查
快速诊断命令(Linux环境):
bash复制# CPU负载
top -H -p $(pgrep -d',' mysqld)
# 磁盘IO
iostat -xmt 1
# 内存
free -h && vmstat 3
# 网络
sar -n DEV 1
重点关注:
- CPU:mysqld进程的%CPU持续>80%
- 磁盘:%util > 70% 或 await > 20ms
- 内存:swap使用量突然增长
- 网络:retrans/s > 0
1.4 索引有效性验证
对可疑查询执行EXPLAIN:
sql复制EXPLAIN FORMAT=JSON
SELECT * FROM orders WHERE user_id = 100 AND status = 'pending';
关键检查点:
type列:应避免ALL(全表扫描),最好达到ref或rangekey列:确认实际使用的索引rows列:预估扫描行数是否过大Extra列:是否出现"Using filesort"或"Using temporary"
案例:某电商平台促销时,一个本该走联合索引的查询突然变成全表扫描,原因是统计信息过期导致优化器选错索引。通过
ANALYZE TABLE解决了问题。
1.5 数据库内部状态指标
关键诊断SQL:
sql复制-- InnoDB状态
SHOW ENGINE INNODB STATUS\G
-- 表缓存命中率
SELECT
(1 - SUM(number_of_entries_in_use) / SUM(number_of_entries)) * 100 AS cache_hit_rate
FROM information_schema.innodb_buffer_pool_stats;
-- 锁等待
SELECT * FROM sys.innodb_lock_waits;
重点关注:
- BUFFER POOL:free buffers不足可能需调整innodb_buffer_pool_size
- ROW OPERATIONS:大量insert buffer合并可能预示写入瓶颈
- SEMAPHORES:大量线程等待信号量说明内部争用严重
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 深度诊断工具链配置
2.1 慢查询日志标准化配置
推荐MySQL配置(my.cnf):
ini复制[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1 # 超过1秒记录
log_queries_not_using_indexes = 1
log_throttle_queries_not_using_indexes = 10 # 限制每分钟记录数量
log_slow_admin_statements = 1
log_slow_slave_statements = 1
日志分析工具链:
bash复制# 原始日志查看
mysqldumpslow -s t /var/log/mysql/mysql-slow.log
# 可视化分析(pt-query-digest)
pt-query-digest --limit=10 --filter '$event->{fingerprint} =~ m/^SELECT/' \
/var/log/mysql/mysql-slow.log > slow_report.txt
2.2 性能模式(Performance Schema)深度配置
启用关键监控项:
sql复制-- 开启语句监控
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES'
WHERE NAME LIKE '%events_statements%';
-- 开启等待事件监控
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES'
WHERE NAME LIKE '%events_waits%';
-- 开启事务监控
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES'
WHERE NAME LIKE '%events_transactions%';
常用诊断视图:
sql复制-- 最耗时的SQL模板
SELECT digest_text, count_star, avg_timer_wait/1000000000 as avg_ms
FROM performance_schema.events_statements_summary_by_digest
ORDER BY avg_timer_wait DESC LIMIT 10;
-- 文件IO等待统计
SELECT * FROM sys.io_global_by_wait_by_latency
WHERE event_name LIKE '%file%';
2.3 操作系统级监控集成
生产环境推荐配置:
- Prometheus + Grafana监控体系
- mysql_exporter采集数据库指标
- node_exporter采集系统指标
- 关键仪表盘配置:
- QPS/TPS变化曲线
- 连接数使用率
- 慢查询速率
- InnoDB缓冲池命中率
- 磁盘IOPS和延迟
3. 典型场景的应急处理方案
3.1 突发CPU飙升处理流程
-
快速定位问题会话:
sql复制SELECT t.*, sys.format_time(timer_wait) AS latency, thread_id, processlist_id FROM performance_schema.events_statements_history_long t JOIN performance_schema.threads USING (thread_id) ORDER BY timer_wait DESC LIMIT 5; -
紧急终止会话:
sql复制-- MySQL KILL CONNECTION processlist_id; -- Oracle ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE; -
事后分析:
- 检查SQL是否缺少索引
- 验证是否存在执行计划突变
- 排查是否有异常批量操作
3.2 磁盘IO饱和应对措施
临时缓解方案:
sql复制-- 降低刷盘频率(需权衡数据安全)
SET GLOBAL innodb_io_capacity = 200;
SET GLOBAL innodb_flush_neighbors = 0;
-- 调整读IO线程数
SET GLOBAL innodb_read_io_threads = 8;
长期优化方向:
- 升级SSD硬件
- 优化表结构避免大字段
- 考虑分库分表方案
3.3 连接数暴增处理手册
紧急扩容:
sql复制-- 临时增加最大连接数
SET GLOBAL max_connections = 1000;
连接池泄漏排查:
bash复制# 统计各客户端的连接数
SELECT SUBSTRING_INDEX(HOST,':',1) AS client,
COUNT(*) AS connections
FROM information_schema.processlist
GROUP BY client ORDER BY connections DESC;
预防措施:
- 配置连接池健康检查
- 设置合理的wait_timeout
- 实现连接复用机制
4. 长效优化机制建设
4.1 索引健康度巡检系统
自动化检查脚本示例:
python复制import pymysql
from pymysql.cursors import DictCursor
def check_index_health(conn):
sql = """
SELECT table_schema, table_name, index_name,
ROUND(stat_value * @@innodb_page_size / 1024 / 1024, 2) AS size_mb,
stat_description
FROM mysql.innodb_index_stats
WHERE stat_name = 'size' AND database_name = %s
ORDER BY size_mb DESC LIMIT 10;
"""
with conn.cursor(DictCursor) as cursor:
cursor.execute(sql, ('your_database',))
return cursor.fetchall()
检查项建议:
- 冗余索引检测
- 低效索引识别(区分度<5%)
- 索引大小监控
- 索引碎片率统计
4.2 执行计划基线管理
关键操作流程:
-
捕获现有高效计划:
sql复制-- MySQL 8.0+ EXECUTE IMMEDIATE 'CREATE OUTLINE FROM SQL'; -- Oracle EXEC DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE( sql_id => 'g4w8hj6t1h3p7'); -
计划绑定验证:
sql复制SELECT * FROM dba_sql_plan_baselines WHERE sql_text LIKE '%orders%'; -
自动演化机制:
sql复制BEGIN DBMS_SPM.CONFIGURE('plan_retention_weeks', 4); DBMS_SPM.SET_EVOLVE_TASK_PARAMETER( 'SYS_AUTO_SPM_EVOLVE_TASK', 'ACCEPT_PLANS', 'TRUE'); END;
4.3 容量规划预警模型
核心指标预测方法:
sql复制-- 根据历史增长预测表大小
SELECT
table_name,
ROUND(data_length/1024/1024) AS current_size_mb,
ROUND(data_length/1024/1024 * POWER(1.1,
DATEDIFF(DATE_ADD(CURDATE(), INTERVAL 3 MONTH), CURDATE())/30)
) AS predicted_size_3month_mb
FROM information_schema.tables
WHERE table_schema = 'your_db';
预警阈值建议:
- 磁盘空间:剩余<20%时预警
- 内存使用:>80%持续1小时触发告警
- 连接数:峰值达到max_connections的70%需扩容
5. 全链路性能优化实践
5.1 应用层优化策略
缓存设计要点:
- 多级缓存架构:
- 客户端缓存(HTTP Cache-Control)
- 应用本地缓存(Caffeine)
- 分布式缓存(Redis)
- 缓存失效策略:
- 高频数据:TTL+主动刷新
- 关键数据:版本号验证
- 防雪崩措施:
- 互斥锁重建
- 缓存预热
- 降级方案
5.2 数据库配置调优
InnoDB关键参数(针对16核64GB内存服务器):
ini复制[mysqld]
innodb_buffer_pool_size = 48G # 物理内存的70-80%
innodb_buffer_pool_instances = 8
innodb_io_capacity = 2000 # SSD建议值
innodb_io_capacity_max = 4000
innodb_flush_neighbors = 0 # SSD建议关闭
innodb_read_io_threads = 8
innodb_write_io_threads = 4
innodb_purge_threads = 4
innodb_adaptive_hash_index = OFF # 高并发时建议关闭
5.3 架构级解决方案
分库分表实施路径:
- 垂直拆分:
- 按业务模块分离(用户库、订单库)
- 大字段独立存储
- 水平拆分:
- 范围分片(按时间、ID区间)
- 哈希分片(user_id % 16)
- 中间件选型:
- ShardingSphere
- MyCat
- Vitess
读写分离部署方案:
mermaid复制(注:根据规范要求,此处不应包含mermaid图表,改为文字描述)
主从架构配置:
1. 主库:承担所有写操作+核心业务读
2. 从库1:报表查询专用(可配置更强大CPU)
3. 从库2:应用程序常规读请求
4. 从库3:备份专用(延迟同步)
路由策略:
- 写操作强制走主库
- 读操作按业务特征路由
- 关键业务读可指定主库
实施要点:
- 复制延迟监控
- 故障自动转移
- 读写分离中间件(如ProxySQL)
