常见问题排查方案

线上问题排查思路

系统日志:CPU,内存,磁盘IO,网络(延迟,丢包)

应用日志:JVM,GC 分析,堆内存,线程状态

中间件:数据库(死锁,慢 SQL),数据库连接池满

Java 死锁:挂起,不响应请求,cpu 下降

//jstack -l > threaddump.txt 导出进程内线程日志

主要表现是 CPU 升高高后下降

查看 deadlock相关信息

优化方案:一次性获取所有锁,顺序获取,设置超时时间,不存在互斥情况可以使用 threadlocal 等

慢SQL 排查

事前 开启慢SQL日志,然后根据超时时间排查

推荐专业的 APM/监控平台

现代应用通常依赖专业的监控工具来实时发现和诊断问题。

  • Prometheus + Grafana: 配合 mysqld_exporter 收集 MySQL 指标(如 QPS、TPS、缓存命中率),通过图表实时显示数据库性能趋势。
  • 云服务商的性能分析工具 (如 AWS RDS Performance Insights): 提供图形化界面,显示最慢的 SQL 语句、等待时间、等待事件等。
  • SkyWalking / New Relic / Pinpoint 等 APM (Application Performance Monitoring) 工具: 追踪请求在应用服务和数据库之间的调用链,可以直接定位导致某个业务请求变慢的具体 SQL 语句。

慢 sql explain分析

id table type key key_len rows extra

EXPLAIN 关键指标 含义及优化目标
**<font style="color:rgb(68, 71, 70);">type</font>** 连接类型。 决定了查询的访问级别。目标是达到 **<font style="color:rgb(68, 71, 70);">const</font>**
> **<font style="color:rgb(68, 71, 70);">eq_ref</font>**
> **<font style="color:rgb(68, 71, 70);">ref</font>**
> **<font style="color:rgb(68, 71, 70);">range</font>**
最差的情况是 <font style="color:rgb(68, 71, 70);">ALL</font>
(全表扫描)。
**<font style="color:rgb(68, 71, 70);">possible_keys</font>** MySQL 认为可能用到的索引。
**<font style="color:rgb(68, 71, 70);">key</font>** MySQL 实际使用的索引。 如果此处为 <font style="color:rgb(68, 71, 70);">NULL</font>
,则表示没有使用索引。
**<font style="color:rgb(68, 71, 70);">key_len</font>** 索引中使用的字节数。<font style="color:rgb(68, 71, 70);">key_len</font>
越短越好(在保证唯一性的前提下)。
**<font style="color:rgb(68, 71, 70);">rows</font>** 估计扫描的行数。 数值越小越好。行数过大是性能差的主要指标。
**<font style="color:rgb(68, 71, 70);">Extra</font>** 额外信息。****目标是避免以下警告: * **<font style="color:rgb(68, 71, 70);">Using filesort</font>**
需要额外的排序,通常是因为没有使用到索引进行排序。 * **<font style="color:rgb(68, 71, 70);">Using temporary</font>**
需要使用临时表,通常是因为执行了分组 (<font style="color:rgb(68, 71, 70);">GROUP BY</font>
) 或排序 (<font style="color:rgb(68, 71, 70);">ORDER BY</font>
) 但没有合适的索引。

主要是看sql执行的过滤行数,索引情况,排序额外信息

优化 sql 方案有哪些,拆分表,使用索引,避免索引失效,减少返回列*,

语句优化方向有

优化方向 具体方法
精确取数 * 避免 **<font style="color:rgb(68, 71, 70);">SELECT *</font>**
明确指定所需列,减少数据传输和 IO 开销。 * 小而精: 使用 <font style="color:rgb(68, 71, 70);">LIMIT</font>
限制返回行数;避免子查询,尽量用 <font style="color:rgb(68, 71, 70);">JOIN</font>
代替;避免 <font style="color:rgb(68, 71, 70);">OR</font>
连接大范围查询。
分页优化 * 深度分页优化: 针对 <font style="color:rgb(68, 71, 70);">LIMIT offset, count</font>
<font style="color:rgb(68, 71, 70);">offset</font>
很大的情况,使用延迟关联主键限定来优化。例如,先通过索引找到起始行的主键,再通过主键快速关联获取数据。
连接优化 * 避免全连接: 确保 <font style="color:rgb(68, 71, 70);">JOIN</font>
关联的字段有索引且数据类型一致。 * 大表驱动小表: 优化 <font style="color:rgb(68, 71, 70);">IN</font>
<font style="color:rgb(68, 71, 70);">EXISTS</font>
通常让小表驱动大表。

外部配置

使用sql 缓存池(热点数据和索引)innodb_buffer_pool_size,

使用 sql 连接池等,ssd 硬盘等

导入导出内存溢出

日志定位存在 Java heap space OOM

提前 dump 命令 HeapDumpOOMError HeapDumpPath = xxx 地址

使用 MAT 分析或者 Jvisualvm

线上导入导出导致的 OOM (Out Of Memory) 异常,通常是因为在处理大文件或海量数据时,程序一次性将所有数据加载到内存中,或者未能及时释放对象

排查这类 OOM 问题的核心思路是:确认 OOM 类型 -> 捕获现场数据 -> 分析内存快照 -> 改进代码的数据处理模式

以下是详细的排查方向和步骤:


🛑 线上导入导出 OOM 排查步骤

阶段一:确认 OOM 类型与现场

首先要确定抛出的是哪种类型的 OOM,以及程序当时正在做什么。

OOM 类型 原因分析 应对措施
**Java heap space** 最常见。 堆内存不足。大量数据对象(如 List、Map、Excel Cell 对象)占用过多内存。 增大堆内存 (治标);内存泄漏或大对象 (治本)。
**GC overhead limit exceeded** GC 频繁且效果甚微。程序花费了大量时间在 GC 上,但回收的内存很少,导致应用执行效率极低。 内存泄漏或堆太小。
**Metaspace** 元空间不足。通常与导入导出无关,但如果涉及大量类的动态加载(如反射、动态代理),可能出现。 增大 Metaspace 大小。

操作: 检查应用日志,获取完整的 OOM 堆栈信息。

阶段二:捕获内存快照(Heap Dump)

内存快照(Heap Dump)是分析 OOM 的唯一数据源,它记录了 OOM 发生时的所有对象信息。

  1. 自动生成 Heap Dump:

在 JVM 启动参数中添加以下参数,让 JVM 在 OOM 发生时自动生成 .hprof 文件:

- Bash
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/path/to/dump/app.hprof
  1. 手动生成 Heap Dump(卡顿但未 OOM):

如果应用已经卡顿但尚未 OOM,可以使用 jmap 手动捕获:

- Bash
jmap -dump:format=b,file=/path/to/dump/manual.hprof <PID>

阶段三:分析内存快照(Heap Analysis)

使用专业的分析工具(如 MAT (Memory Analyzer Tool)JVisualVM)打开 .hprof 文件进行分析。

  1. 查找最大的对象(Dominator Tree):
    • 在分析工具中查看 Dominator Tree(支配树) 视图。
    • 关注点: 查找占用内存比例最高的对象。在导入导出场景中,这些对象通常是:
      • ArrayListHashMap 实例,里面存储了海量行数据对象。
      • byte[]char[],可能存储了整个大文件的原始内容。
      • String 对象,如果字符串数量巨大或出现重复字符串(但未被优化)。
  2. 分析对象引用链(Path to GC Root):
    • 一旦找到最大的对象,右键点击并查看其“Path to GC Root”(引用链)
    • 目标: 确定该大对象被哪个线程静态变量等 GC Root 所持有,从而定位到是哪一段代码未能及时释放引用。

改用流式读取,sql 流式查询,逐行处理,批量提交等

频繁 FullGC

打印 gc 详细日志

PrintGCDetails gc.log

//jstat 或者 arthas dashboard

Eden survior Old

堆内存 jmap 生成

是否存在大对象到 old Gen 解决方案 临时调整大小缓解 修改代码

OOM问题

以上同步,但是要注意可能情况,Error 日志 Heap Dump 日志堆转存文件 GC 日志

分析 Heap Dump,大对象/内存泄露问题

大对象集合/长生命周期/无限增长/缓存未清理等

CPU 飙高

可以通过 top 命令查询进程

然后使用top hd 查询内部线程

jstack 转16进制 查询对应线程程信息

可能原因有

1.死循环

2.频繁垃圾回收

3.死锁问题

MySQL 死锁问题

show engine innodb status 查看状态找到 LATEST DETECTED DEADLOCK部分,

解决方案顺序一致性获取锁,减少事务范围,乐观锁版本号实现呢

可以加适当的索引/最好使用行级锁

预防.设置死锁监控记录错误日志

MySQL 数据库连接满

show processlist,show full processlist,查询占用连接

慢日志情况,是否正确关闭,有没有连接泄露问题,是不是有长连接

合理配置,使用 mysql 性能配置

优化方案,慢查询优化,增大最大连接数?连接泄露问题?分库分表解决.开启监控

Java 进程突然挂了

系统日志,应用日志分析,内存不足?栈溢出?堆内存分析,

cpu top命令,

内存使用 free -m 磁盘 df -h

栈溢出死循环,使用oom 不存在内存不足

线上系统接口响应慢/突然响应慢

使用工具查看响应时间,吞吐量,错误率

Skywalking Promethus 等

数据库性能分析

外部依赖 api 分析

突然响应慢

系统资源问题?

应用监控

数据库性能?

线程进程分析

网络分析

压力测试

高并发的线程安全问题

查看并发控制 synchronized volatile lock等

共享资源访问

线程安全集合

日志分析

cpu 分析内存分析

压测工具

线上大量错误日志

1.elk收集存储日志

2.日志优先级排序

3.快速定位和分析,关键字,时间和频率,上下文信息

4.深入调查是代码还是其他问题等

5.解决问题

6.验证并总结优化

posted @ 2025-12-04 23:23  8023渡劫  阅读(7)  评论(0)    收藏  举报