日常问题排查手册

------------------------------------------------------------------------------------------------------

springboot日常问题排查工具

SpringBoot 线上 / 日常问题排查全套工具(运维 + 开发必备,直接照着用)

一、JDK 自带原生工具(无需安装,万能)

  1. jps查看 Java 进程 PIDjps -l
  2. jstack PID排查线程死锁、线程阻塞、CPU 飙高、接口卡死导出线程堆栈,分析等待、死锁、阻塞
  3. jmap PID / jheapdump排查内存溢出 OOM、内存泄漏、堆内存占用过高生成堆快照
  4. jstat监控 GC 频繁、GC 卡顿、内存回收异常
  5. jconsole / VisualVM可视化监控:内存、线程、GC、类加载、CPU本地 + 远程都能用

二、SpringBoot 自带监控神器(Actuator)

引入依赖即可开箱即用
xml
 
 
spring-boot-starter-actuator
 
常用端点:
  • /actuator/health 服务健康
  • /actuator/beans 所有 Bean
  • /actuator/dump 线程堆栈
  • /actuator/env 配置参数
  • /actuator/logfile 实时日志
  • /actuator/metrics CPU、内存、接口耗时
配合 Prometheus + Grafana 做大盘监控

三、线上性能诊断神器 Arthas(阿里开源,必用)

无脑一键排查:CPU 高、慢接口、死锁、参数不对、异常堆栈、接口耗时
  1. 一键附着进程
  2. dashboard 全局概览
  3. thread 查看线程
  4. watch 实时查看方法入参出参
  5. trace 追踪接口调用耗时链路
  6. heapdump 导出内存快照
微服务排查首选,比 JDK 工具好用 10 倍

四、日志排查工具

  1. Logback/Log4j2 日志分级 ERROR/WARN/INFO
  2. ELK / Loki 集中日志检索,海量日志秒查
  3. Arthas 实时打印方法日志,不用改代码

五、接口 & 链路排查

  1. Sleuth + Zipkin 微服务 OpenFeign 调用链路追踪
     
    排查:哪个服务慢、哪个接口超时、调用断层
  2. Knife4j/Swagger 接口参数、响应异常
  3. Postman 复现线上接口异常

六、常见问题 + 对应工具

  1. 服务 CPU 飙升 → Arthas thread / jstack
  2. 内存爆满 OOM → jmap / Arthas heapdump
  3. 接口超时卡死无响应 → jstack + trace
  4. 事务不回滚、分布式事务异常 → 日志 + Seata 控制台
  5. Feign 调用失败、超时 → Sleuth 链路追踪
  6. Bean 注入失败、配置不生效 → actuator/env/beans
  7. GC 频繁卡顿 → jstat、VisualVM

七、极简记忆口诀

  • 线程卡死:jstack / Arthas thread
  • 内存溢出:jmap / heapdump
  • 接口慢链路乱:Zipkin 链路追踪
  • 线上临时排查:Arthas 一键神器
  • 健康配置监控:Actuator
需要我给你整理Arthas 常用一键排查命令大全吗?
数据库死锁排查

MySQL + SpringBoot 数据库死锁 全套排查方法(线上直接用)

一、MySQL 查看当前死锁日志(必用)

sql
 
 
-- 查看最近一次死锁详情
show engine innodb status;
 
往下找到 LATEST DETECTED DEADLOCK里面会清清楚楚显示:
  • 哪个事务、哪条 SQL
  • 谁持有行锁
  • 谁等待锁
  • 锁等待顺序、循环等待 → 死锁原因

二、查看当前正在锁等待的事务

sql
 
 
-- 查看正在等待锁的事务
select * from information_schema.innodb_lock_waits;

-- 查看所有运行事务
select * from information_schema.innodb_trx;
 

三、SpringBoot 事务 + Feign 最常见死锁场景

  1. 服务 A 更新表 1 → Feign 调用服务 B 更新表 2
  2. 服务 B 反过来更新表 1互相等待对方行锁 → 环形死锁
  3. 同一批数据多线程更新顺序不一致线程 1:先改 id=1 再改 id=2线程 2:先改 id=2 再改 id=1→ 99% 必出死锁
  4. @Transactional 传播级别配置错误嵌套事务、 REQUIRES_NEW 混用导致长事务不释放锁

四、Java 层面排查长事务(锁持有太久)

  1. Arthas 查看事务持有时长
  2. 排查是否:
    • 事务里调用 Feign 远程(超级大忌!)
    • 事务里查数据库循环
    • 事务里 IO、文件、等待
Spring 事务内不要写 OpenFeign 调用!远程耗时越长,锁持有越久,死锁爆炸概率翻倍

五、死锁快速定位流程图

plaintext
 
 
出现锁超时/死锁报错
        ↓
show engine innodb status 看死锁日志
        ↓
看两个事务SQL更新顺序是否颠倒
        ↓
统一所有线程更新ID排序(从小到大)
        ↓
缩短事务时长、事务内不远程调用
        ↓
innodb锁级别优化 RC 代替 RR
 

六、根治死锁 3 个黄金方案

  1. 所有多线程更新多行,必须按主键 ID 顺序统一更新
  2. @Transactional 事务尽可能短小,事务内禁止 Feign、RPC
  3. MySQL 隔离级别改用 READ COMMITTED(大幅减少间隙锁死锁)

七、线上快速杀阻塞事务

sql
 
 
-- 查到trx_mysql_thread_id
kill 线程ID;
 

要不要我给你MySQL 死锁日志解读模板,你粘贴日志我一秒帮你定位是谁跟谁互锁?
mysql 如何执行死锁语句

MySQL 手动模拟死锁(2 个会话同时执行,100% 复现)

准备:2 个 MySQL 查询窗口(会话 A、会话 B)

MySQL 隔离级别默认 RR(可重复读) 即可

测试表

sql
 
 
CREATE TABLE t_lock(
id INT PRIMARY KEY,
name VARCHAR(20)
);

INSERT INTO t_lock VALUES(1,'a'),(2,'b');
 

步骤 1:会话 A 执行

sql
 
 
BEGIN;
UPDATE t_lock SET name='aa' WHERE id=1;
 
会话 A 锁住 id=1

步骤 2:会话 B 执行

sql
 
 
BEGIN;
UPDATE t_lock SET name='bb' WHERE id=2;
 
会话 B 锁住 id=2

步骤 3:会话 A 再执行

sql
 
 
UPDATE t_lock SET name='aaa' WHERE id=2;
 
会话 A 等待 会话 B 的 id=2 锁

步骤 4:会话 B 再执行

sql
 
 
UPDATE t_lock SET name='bbb' WHERE id=1;
 
👉 立刻触发死锁!
plaintext
 
 
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
 

查看刚刚产生的死锁日志

sql
 
 
SHOW ENGINE INNODB STATUS;
 
往下找到 LATEST DETECTED DEADLOCK 就是完整死锁信息

为什么会死锁?

  1. A 占 1,等 2
  2. B 占 2,等 1
     
    循环等待 → 死锁

SpringBoot+MySQL 高频死锁元凶

  1. 多线程更新主键顺序不一致
  2. @Transactional 里面调用 Feign 远程,长事务不释放锁
  3. RR 隔离级别间隙锁,范围更新互相等待
需要我顺便教你怎么看死锁日志、怎么根治吗?
mysql执行计划查看

MySQL 执行计划 EXPLAIN 超通俗易懂完整版

1、最简单用法

SQL 前面加 explain
sql
 
 
explain select * from case_info where case_id = '123';
 

2、关键字段看懂(面试 + 排查必背)

1. type 🔴 SQL 好坏等级(最重要)

从好到差:system > const > eq_ref > ref > range > index > ALL
  • ref / eq_ref:走索引,优秀
  • range:范围查询(between/in)一般
  • index:扫描索引全表
  • ALL:全表扫描!垃圾 SQL,必加索引

2. key

  • 显示实际用到的索引
  • NULL = 没走索引

3. rows

MySQL 预估扫描多少行数据,越小越快

4. Extra 额外信息

  • Using index:覆盖索引,极好
  • Using filesort:文件排序,很慢,order by 没索引
  • Using temporary:临时表,group by 差
  • Using join buffer:join 没索引

5. possible_keys

可能用到的所有索引

3、常见问题一眼判断

  1. type=ALL → 没走索引,加索引
  2. Extra=Using filesort → order by 字段建索引
  3. Extra=Using temporary → group by 优化
  4. rows 几百万 → 大 SQL 慢查询

4、进阶详细执行计划

sql
 
 
explain extended select ... ;
show warnings;
 
可以看到 MySQL真实优化后的 SQL

5、你案件业务高频慢 SQL 场景

  1. 附件表、案件表没加 caseId 索引 → ALL 全表扫描
  2. 多表 join 关联字段没索引
  3. 事务 + 大查询 → 锁等待 + 慢 SQL 叠加死锁

------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------

posted @ 2026-04-21 11:16  hanease  阅读(5)  评论(0)    收藏  举报