一、磁盘空间满但未释放问题
现象
df -h 显示磁盘使用率100%
du -sh * 查看目录占用与df结果不匹配
文件已被删除但空间未释放
根本原因
文件被进程占用,即使执行rm删除,只要进程仍持有文件句柄,磁盘空间就不会释放。
排查步骤
bash
1. 查找被删除但仍被占用的文件
bash
lsof | grep deleted
或更精确的查询
bash
lsof +L1 # 显示链接数小于1的文件
2. 查看具体进程信息
bash
lsof | grep deleted | awk '{print $1,$2,$NF}' | sort | uniq
3. 确认文件大小和进程
bash
ls -lh /proc/<PID>/fd/ | grep deleted
4. 查看哪些进程占用最多
bash
lsof | grep deleted | awk '{print $2}' | sort | uniq -c | sort -rn
解决方案
方法一:优雅重启相关服务
bash
# 找到占用文件的进程
PID=$(lsof | grep deleted | head -1 | awk '{print $2}')
bash
# 查看是什么服务
ps aux | grep $PID
bash
# 根据服务类型重启(如nginx, mysql, java应用等)
systemctl restart service_name
或
bash
service service_name restart
方法二:清理进程句柄(谨慎使用)
bash
# 方式1: 向进程发送信号,让其重新打开日志文件
kill -HUP <PID>
bash
# 方式2: 清空文件内容(如果确定文件可清理)
cat /dev/null > /proc/<PID>/fd/<FD_NUM>
bash
# 方式3: 强制结束进程(最后手段)
kill -9 <PID>
预防措施
日志轮转配置
bash
# logrotate配置示例
/var/log/application/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 root root
postrotate
/usr/bin/killall -HUP application_name
endscript
}
监控告警设置
磁盘使用率>85%触发警告
90%触发紧急告警
使用Prometheus+Alertmanager或Zabbix监控
定期清理脚本
bash
#!/bin/bash
# 清理7天前的日志
find /var/log -name "*.log" -type f -mtime +7 -delete
# 清理/tmp目录
find /tmp -type f -atime +1 -delete
二、Java进程CPU占用超100%
现象
top命令显示Java进程CPU使用率>100%(多核系统)
系统响应缓慢,可能有线程死锁或频繁GC
排查流程
步骤1:定位高CPU线程
bash
# 查看Java进程PID
top -c | grep java
ps aux | grep java
bash
# 查看该进程的所有线程
top -H -p <PID>
bash
# 或
ps -eLf | grep <PID> | head -20
步骤2:转换线程ID
将十进制的线程ID转为十六进制(用于jstack)
bash
printf "%x\n" <线程ID>
步骤3:获取线程堆栈
使用jstack获取线程堆栈
bash
jstack <PID> > jstack_$(date +%Y%m%d_%H%M%S).log
或直接查找特定线程
bash
jstack <PID> | grep -A 10 <十六进制线程ID>
步骤4:分析GC情况
查看GC状态
bash
jstat -gcutil <PID> 1000 5
开启GC日志(JVM参数)
bash
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/to/gc.log
常见问题及解决方案
- 线程死锁
特征:
多个线程长期处于BLOCKED状态
线程等待同一个锁
排查:
bash
jstack <PID> | grep -A 5 "BLOCKED"
或直接检测死锁
bash
jstack <PID> | grep -i deadlock
解决:
检查同步代码块
使用ReentrantLock替代synchronized
设置锁超时时间
- 频繁GC
特征:
CPU使用率周期性飙升
jstat显示频繁的Full GC
排查:
bash
# 查看堆内存使用
jmap -heap <PID>
# 生成堆转储(生产环境慎用)
jmap -dump:format=b,file=heapdump.hprof <PID>
解决:
JVM调优参数示例
bash
-Xms4g -Xmx4g # 设置相同避免动态调整
-XX:+UseG1GC # 使用G1垃圾收集器
-XX:MaxGCPauseMillis=200 # 目标暂停时间
-XX:InitiatingHeapOccupancyPercent=45 # G1触发混合GC的堆占用率
- 无限循环/递归
特征:
单个线程持续高CPU
堆栈显示重复的方法调用
解决:
检查算法逻辑
添加循环终止条件
设置递归深度限制
工具推荐
Arthas(阿里开源的Java诊断工具)
bash
# 安装运行
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
常用命令
bash
dashboard # 实时监控面板
thread # 查看线程信息
thread -n 3 # 查看最忙的3个线程
jad # 反编译类
watch # 方法执行监控
VisualVM(图形化监控)
JProfiler(商业性能分析工具)
三、Update语句执行全流程
SQL执行架构概览
客户端请求 → 连接层 → SQL层 → 存储引擎层 → 磁盘
详细执行流程
阶段1:连接层(Connector)
功能:
客户端连接管理
身份认证
连接池维护
关键组件:
线程池(Thread Pool)
连接限制(max_connections)
超时设置(wait_timeout)
阶段2:SQL层(SQL Layer)
步骤1:查询解析
sql
-- 原始SQL
UPDATE users SET status = 'active' WHERE id = 100;
-- 解析为抽象语法树(AST)
UpdateStmt
├── Table: users
├── SetClause: status = 'active'
└── WhereClause: id = 100
步骤2:查询优化
基于规则的优化:
条件化简
外连接转内连接
子查询优化
基于成本的优化:
选择最佳索引
连接顺序优化
访问路径选择
步骤3:执行计划生成
bash
-- EXPLAIN查看执行计划
EXPLAIN UPDATE users SET status = 'active' WHERE id = 100;
-- 输出示例:
-- id: 1
-- select_type: UPDATE
-- type: const
-- key: PRIMARY
-- rows: 1
-- Extra: Using where
阶段3:存储引擎层(Storage Engine)
InnoDB引擎Update流程
bash
开始事务 → 读取数据页 → 写undo log → 修改数据 → 写redo log → 提交事务
详细步骤:
事务开始
获取事务ID
设置事务隔离级别
数据读取
或使用pt-query-digest
总结对比表
问题类型 关键命令 解决思路 预防措施
磁盘未释放 lsof | grep deleted 重启持有文件的服务 配置日志轮转,监控磁盘
Java高CPU top -H, jstack 分析线程堆栈,优化GC 代码review,JVM调优
SQL执行慢 EXPLAIN, SHOW PROCESSLIST 优化索引,调整配置 定期分析慢查询,监控
快速排查检查清单
磁盘空间紧急处理
df -h 确认磁盘使用率
lsof | grep deleted 查找被占用的文件
确定相关服务并重启
清理临时文件和日志
设置监控告警
Java进程诊断
bash
top -H -p <PID> 定位高CPU线程
printf "%x" <TID> 转换线程ID
jstack <PID> \| grep -A 10 <nid> 分析线程堆栈
jstat -gcutil <PID> 检查GC状态
根据分析结果优化代码或JVM参数
SQL优化检查
EXPLAIN 分析执行计划
检查索引使用情况
避免全表扫描和大事务
优化查询语句和表结构
调整数据库配置参数
适用场景:Linux服务器运维、Java应用维护、MySQL数据库管理
注意:生产环境操作前务必在测试环境验证,高危操作建议在业务低峰期进行。