三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

数据库性能排查五步法:从慢查询到系统资源优化

数据库性能排查五步法:从慢查询到系统资源优化

1. 数据库性能排查的黄金五步法

当线上数据库出现性能问题时,很多DBA会陷入手忙脚乱的状态。根据我多年处理生产环境数据库性能问题的经验,建议按照以下五个关键检查点进行系统性排查。这套方法在MySQL、Oracle等主流关系型数据库中普遍适用,能快速定位80%以上的性能瓶颈。

重要提示:性能排查一定要有方法论,避免无头苍蝇式的检查。以下顺序是根据问题出现概率和排查效率优化的结果。

1.1 第一步:检查慢查询日志

慢查询日志是数据库性能问题的第一现场证据。以MySQL为例,通过以下配置开启慢查询监控:

-- 查看当前慢查询配置 SHOW VARIABLES LIKE 'slow_query%'; SHOW VARIABLES LIKE 'long_query_time'; -- 临时设置慢查询阈值(单位:秒) SET GLOBAL long_query_time = 1; SET GLOBAL slow_query_log = 'ON';

关键分析要点:

  • 重点关注执行时间超过阈值的TOP 10查询
  • 检查出现频率高的重复查询模式
  • 注意没有使用索引的查询(rows_examined远大于rows_sent)

典型问题特征:

# Query_time: 5.123456 Lock_time: 0.000123 Rows_sent: 2 Rows_examined: 500000 SELECT * FROM orders WHERE status = 'pending' AND create_time > '2023-01-01';

这个查询扫描了50万行却只返回2条数据,明显存在索引缺失问题。

1.2 第二步:EXPLAIN分析执行计划

对发现的慢SQL必须使用EXPLAIN进行执行计划分析:

EXPLAIN SELECT * FROM users WHERE username LIKE 'john%' AND age > 25;

需要重点关注的字段:

字段正常值异常值问题原因
typeconst/ref/rangeALL全表扫描
key索引名NULL未使用索引
rows小数大数扫描行数过多
ExtraUsing indexUsing filesort需要优化排序

常见问题处理:

  • 出现Using temporary:查询需要优化临时表使用
  • Using filesort:需要添加合适的索引优化排序
  • Select tables optimized away:这是理想状态

1.3 第三步:索引有效性检查

索引是数据库性能的核心。检查索引问题需要多维度验证:

  1. 索引缺失检查
-- 查找WHERE条件中常用但未索引的列 SELECT * FROM sys.schema_unused_indexes WHERE object_schema = 'your_db'; -- 查找高选择性的未索引列 SELECT column_name, count(*) as cnt FROM table_name GROUP BY column_name ORDER BY cnt DESC LIMIT 10;
  1. 索引冗余检查
-- 查找重复或冗余索引 SELECT * FROM sys.schema_redundant_indexes;
  1. 索引使用统计
-- 查看索引使用频率 SELECT * FROM sys.schema_index_statistics WHERE table_schema = 'your_db';

索引优化经验法则:

  • 为高频查询条件创建复合索引
  • 遵循最左前缀原则设计索引
  • 避免在索引列上使用函数
  • 区分度低的列不适合单独建索引

1.4 第四步:系统资源监控

当SQL本身没问题时,需要检查系统资源状况:

  1. 数据库连接数
SHOW STATUS LIKE 'Threads_connected'; SHOW VARIABLES LIKE 'max_connections';
  1. 缓冲池使用率
-- InnoDB缓冲池命中率 SELECT (1 - (SELECT variable_value FROM performance_schema.global_status WHERE variable_name = 'Innodb_buffer_pool_reads') / (SELECT variable_value FROM performance_schema.global_status WHERE variable_name = 'Innodb_buffer_pool_read_requests')) * 100 AS buffer_pool_hit_ratio;
  1. 锁等待情况
-- 查看当前锁等待 SELECT * FROM sys.innodb_lock_waits; -- 长事务检查 SELECT * FROM information_schema.innodb_trx WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60;

关键阈值参考:

  • 连接数使用率 > 70% 需要预警
  • 缓冲池命中率 < 95% 需要优化
  • 锁等待时间 > 500ms 需要关注

1.5 第五步:硬件I/O性能检查

最后需要排除硬件层面的瓶颈:

  1. 磁盘I/O延迟
# Linux下检查磁盘延迟 iostat -dx 1

关注await列,正常应<10ms

  1. SWAP使用情况
free -h vmstat 1

swap使用率>0说明内存不足

  1. 网络延迟
ping -c 5 database_host traceroute database_host

数据库网络延迟应<1ms

2. 典型性能问题处理实录

2.1 案例一:索引失效导致查询变慢

问题现象: 用户报告订单查询接口响应时间从200ms突增到5s

排查过程

  1. 从慢日志发现大量类似查询:
SELECT * FROM orders WHERE user_id = 123 AND status = 'completed' ORDER BY create_time DESC LIMIT 10;
  1. EXPLAIN显示全表扫描:
type: ALL key: NULL rows: 500000 Extra: Using filesort
  1. 检查现有索引:
SHOW INDEX FROM orders; -- 发现只有单独的user_id索引和status索引

解决方案: 创建复合索引:

ALTER TABLE orders ADD INDEX idx_user_status_time(user_id, status, create_time);

效果验证: 执行计划变为:

type: ref key: idx_user_status_time rows: 15 Extra: Backward index scan

查询时间恢复至50ms左右

2.2 案例二:连接池耗尽导致服务不可用

问题现象: 应用频繁报"Too many connections"错误

排查过程

  1. 检查连接数:
SHOW STATUS LIKE 'Threads_connected'; -- 显示400/400
  1. 查看连接来源:
SELECT user, host, db, command, time FROM information_schema.processlist;
  1. 发现大量sleep状态的连接:
| app_user | 10.0.0.% | orders_db | Sleep | 500 |

问题原因: 应用未正确关闭数据库连接,连接池配置过大导致耗尽

解决方案

  1. 优化应用连接管理
  2. 设置连接超时:
SET GLOBAL wait_timeout = 60; SET GLOBAL interactive_timeout = 60;
  1. 使用连接池中间件

3. 性能优化工具箱

3.1 必备监控命令

命令用途关键指标
SHOW ENGINE INNODB STATUSInnoDB状态锁等待、死锁
SHOW PROCESSLIST当前会话长事务、阻塞操作
SHOW GLOBAL STATUS全局状态QPS、TPS、缓存命中率
SHOW GLOBAL VARIABLES系统变量配置参数检查

3.2 常用性能分析工具

  1. pt-query-digest
# 分析慢查询日志 pt-query-digest /var/log/mysql/mysql-slow.log
  1. sys schema
-- 查看未使用索引 SELECT * FROM sys.schema_unused_indexes; -- 查看冗余索引 SELECT * FROM sys.schema_redundant_indexes;
  1. Percona Toolkit
  • pt-index-usage:索引使用分析
  • pt-visual-explain:可视化执行计划

4. 预防性维护建议

4.1 日常监控项

  1. 关键指标监控
  • QPS/TPS波动
  • 慢查询数量变化
  • 连接数使用率
  • 缓冲池命中率
  1. 定期健康检查
-- 每周执行一次 ANALYZE TABLE important_table; OPTIMIZE TABLE fragmented_table;

4.2 容量规划要点

  1. 磁盘空间监控:
  • 数据文件增长趋势
  • 日志文件轮转情况
  1. 性能基准测试:
  • 业务高峰期前进行压力测试
  • 比较版本升级前后的性能差异

我在实际运维中发现,很多性能问题都是日积月累的小问题爆发的。建议建立定期检查机制,在问题影响用户前就发现并解决。对于核心业务表,最好在开发阶段就进行索引设计和SQL评审,这比事后优化要高效得多。

← 返回列表