运维问题排查笔记:磁盘、Java进程与SQL执行流程

一、磁盘空间满但未释放问题

现象

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

常见问题及解决方案

  1. 线程死锁
    特征:

多个线程长期处于BLOCKED状态

线程等待同一个锁

排查:

bash 复制代码
jstack <PID> | grep -A 5 "BLOCKED"

或直接检测死锁

bash 复制代码
jstack <PID> | grep -i deadlock

解决:

检查同步代码块

使用ReentrantLock替代synchronized

设置锁超时时间

  1. 频繁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的堆占用率
  1. 无限循环/递归
    特征:
    单个线程持续高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数据库管理

注意:生产环境操作前务必在测试环境验证,高危操作建议在业务低峰期进行。

相关推荐
Hello_Embed10 小时前
libmodbus 移植 STM32(基础篇)
笔记·stm32·单片机·学习·modbus
怪兽源码11 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
恒悦sunsite11 小时前
Redis之配置只读账号
java·redis·bootstrap
梦里小白龙11 小时前
java 通过Minio上传文件
java·开发语言
德育处主任Pro11 小时前
『NAS』用SSH的方式连上NAS
运维·ssh
人道领域11 小时前
javaWeb从入门到进阶(SpringBoot事务管理及AOP)
java·数据库·mysql
Meaauf11 小时前
VMware安装中科方德服务器操作系统
运维·服务器·中科方德
南宫码农11 小时前
神马影视8.5版本如意伪静态+视频教程
linux·运维·centos
无聊的小坏坏11 小时前
实习笔记:用 /etc/crontab 实现定期数据/日志清理
笔记·实习日记
香芋Yu11 小时前
【机器学习教程】第04章 指数族分布
人工智能·笔记·机器学习