当前位置:首页>Linux>Linux 内存泄漏与 OOM 问题完全解决指南

Linux 内存泄漏与 OOM 问题完全解决指南

  • 2026-04-19 09:25:13
Linux 内存泄漏与 OOM 问题完全解决指南

从内存泄漏诊断到 OOM 根治


📋 目录速览


🎯 内存问题的典型表现

Linux 系统内存问题症状

快速诊断脚本

#!/bin/bash

# memory_quick_check.sh - Linux 内存问题快速诊断

echo "========== Linux 内存快速诊断 =========="

echo "系统: $(uname -s) $(uname -r)"

echo "主机: $(hostname)"

echo "时间: $(date)"

echo ""

# 1. 内存总览

echo "【内存使用情况】"

free -h

echo ""

# 2. 内存使用率

TOTAL=$(free -m | awk 'NR==2{print $2}')

USED=$(free -m | awk 'NR==2{print $3}')

AVAILABLE=$(free -m | awk 'NR==2{print $7}')

USAGE=$(awk "BEGIN {printf \"%.2f\", $USED * 100 / $TOTAL}")

echo "总内存: ${TOTAL}MB"

echo "已使用: ${USED}MB (${USAGE}%)"

echo "可用: ${AVAILABLE}MB"

if [ $AVAILABLE -lt 100 ]; then

    echo "⚠️  警告: 可用内存不足 100MB!"

elif [ $AVAILABLE -lt 500 ]; then

    echo "⚠️  注意: 可用内存偏低"

fi

echo ""

# 3. 内存详细信息

echo "【内存详细信息】"

cat /proc/meminfo | grep -E "MemTotal|MemFree|MemAvailable|Buffers|Cached|SwapTotal|SwapFree|Slab|SReclaimable|SUnreclaim|Dirty|Writeback"

echo ""

# 4. TOP 10 内存占用进程

echo "【TOP 10 内存占用进程】"

ps aux --sort=-%mem | head -11 | awk '{printf "%-8s %-6s %5s %5s %10s %s\n", $1, $2, $3, $4, $6, $11}'

echo ""

# 5. slab 内存使用

echo "【slab 内存 TOP 10】"

if [ -f /proc/slabinfo ]; then

    echo "名称                    对象数    大小      占用"

    cat /proc/slabinfo | tail -n +3 | awk '{

        name=$1; 

        objs=$3; 

        objsize=$4; 

        mem=objs*objsize/1024/1024;

        if (mem > 1) printf "%-20s %8d %8d %7.2fMB\n", name, objs, objsize, mem

    }' | sort -k4 -rn | head -10

else

    echo "slabinfo 不可用"

fi

echo ""

# 6. swap 使用情况

echo "【swap 使用情况】"

SWAP_TOTAL=$(free -m | awk 'NR==3{print $2}')

SWAP_USED=$(free -m | awk 'NR==3{print $3}')

if [ $SWAP_TOTAL -gt 0 ]; then

    SWAP_PERCENT=$(awk "BEGIN {printf \"%.2f\", $SWAP_USED * 100 / $SWAP_TOTAL}")

    echo "Swap 总量: ${SWAP_TOTAL}MB"

    echo "Swap 使用: ${SWAP_USED}MB (${SWAP_PERCENT}%)"

    if [ $SWAP_USED -gt 0 ]; then

        echo "⚠️  警告: 系统正在使用 swap,可能影响性能"

    fi

else

    echo "未配置 swap"

fi

echo ""

# 7. OOM 历史

echo "【OOM Killer 历史】"

OOM_COUNT=$(dmesg | grep -c "Out of memory")

if [ $OOM_COUNT -gt 0 ]; then

    echo "⚠️  发现 $OOM_COUNT 次 OOM 事件"

    echo "最近 5 次 OOM:"

    dmesg | grep "Out of memory" | tail -5

else

    echo "✅ 无 OOM 记录"

fi

echo ""

# 8. 内存分配失败

echo "【内存分配失败】"

ALLOC_FAIL=$(dmesg | grep -c "page allocation failure")

if [ $ALLOC_FAIL -gt 0 ]; then

    echo "⚠️  发现 $ALLOC_FAIL 次内存分配失败"

    dmesg | grep "page allocation failure" | tail -3

else

    echo "✅ 无内存分配失败记录"

fi

echo ""

# 9. 内存压力(如果支持)

if [ -f /proc/pressure/memory ]; then

    echo "【内存压力】"

    cat /proc/pressure/memory

    echo ""

fi

# 10. 系统负载

echo "【系统负载】"

uptime

echo ""

# 11. 诊断结论

echo "【诊断结论】"

ISSUES=0

if [ $AVAILABLE -lt 100 ]; then

    echo "❌ 严重: 可用内存不足,需要立即处理"

    ISSUES=$((ISSUES + 1))

fi

if [ $SWAP_USED -gt $((SWAP_TOTAL / 2)) ] && [ $SWAP_TOTAL -gt 0 ]; then

    echo "❌ 严重: swap 使用率超过 50%"

    ISSUES=$((ISSUES + 1))

fi

if [ $OOM_COUNT -gt 0 ]; then

    echo "⚠️  警告: 发现 OOM 事件,系统曾经内存不足"

    ISSUES=$((ISSUES + 1))

fi

SUNRECLAIM=$(grep "^SUnreclaim:" /proc/meminfo | awk '{print $2/1024}')

if [ $(echo "$SUNRECLAIM > 500" | bc -l 2>/dev/null || echo 0) -eq 1 ]; then

    echo "⚠️  警告: 不可回收的 slab 内存过多 (${SUNRECLAIM}MB)"

    ISSUES=$((ISSUES + 1))

fi

if [ $ISSUES -eq 0 ]; then

    echo "✅ 正常: 内存使用正常"

fi

echo ""

echo "========== 诊断完成 ========


🏗️ Linux 内存架构

内存分布概览

内存类型详解

# 查看详细内存信息
$ cat /proc/meminfo
MemTotal:        8388608 kB  # 总内存 (8GB)
MemFree:         1048576 kB  # 完全空闲的内存
MemAvailable:    3145728 kB  # 可用内存(包括可回收的)
Buffers:          204800 kB  # 块设备缓冲区
Cached:          2097152 kB  # 页缓存
SwapCached:            0 kB  # swap 缓存
Active:          4194304 kB  # 活跃内存(最近使用)
Inactive:        2097152 kB  # 不活跃内存(可回收)
Active(anon):    3145728 kB  # 活跃的匿名内存(进程内存)
Inactive(anon):   524288 kB  # 不活跃的匿名内存
Active(file):    1048576 kB  # 活跃的文件缓存
Inactive(file):  1572864 kB  # 不活跃的文件缓存
Unevictable:           0 kB  # 不可回收的内存(mlock)
Mlocked:               0 kB  # 锁定的内存
SwapTotal:       2097152 kB  # swap 总大小 (2GB)
SwapFree:        2097152 kB  # swap 空闲
Dirty:             10240 kB  # 脏页(待写入磁盘)
Writeback:             0 kB  # 正在写回的页
AnonPages:       3670016 kB  # 匿名页(进程内存)
Mapped:           524288 kB  # 映射的内存(mmap)
Shmem:            262144 kB  # 共享内存
Slab:             524288 kB  # slab 总大小
SReclaimable:     262144 kB  # 可回收的 slab
SUnreclaim:       262144 kB  # 不可回收的 slab
KernelStack:       16384 kB  # 内核栈
PageTables:        32768 kB  # 页表
NFS_Unstable:          0 kB  # NFS 不稳定页
Bounce:                0 kB  # bounce 缓冲区
WritebackTmp:          0 kB  # 临时写回缓冲区
CommitLimit:     6291456 kB  # 可分配的总内存
Committed_AS:    5242880 kB  # 已分配的内存
VmallocTotal:   34359738367 kB  # vmalloc 总大小
VmallocUsed:      102400 kB  # vmalloc 已使用
VmallocChunk:   34359635967 kB  # vmalloc 最大连续块
HardwareCorrupted:     0 kB  # 硬件损坏的内存
AnonHugePages:    524288 kB  # 匿名大页
HugePages_Total:       0# 大页总数
HugePages_Free:        0# 大页空闲数
HugePages_Rsvd:        0# 大页保留数
HugePages_Surp:        0# 大页剩余数
Hugepagesize:       2048 kB  # 大页大小
DirectMap4k:      524288 kB  # 4KB 直接映射
DirectMap2M:     8388608 kB  # 2MB 直接映射

内存分配器层次


🐛 内存泄漏的常见原因

通用内存泄漏场景

内存泄漏的识别特征


🔧 内存使用分析工具

基础分析工具

高级分析工具

内存监控脚本

#!/bin/bash

# comprehensive_memory_monitor.sh - 综合内存监控

LOG_DIR="/var/log/memory_monitor"

mkdir -p $LOG_DIR

INTERVAL=60  # 监控间隔(秒)

LOG_FILE="$LOG_DIR/memory_$(date +%Y%m%d).log"

echo "========== 内存监控启动 ==========" | tee -a $LOG_FILE

echo "时间: $(date)" | tee -a $LOG_FILE

echo "主机: $(hostname)" | tee -a $LOG_FILE

echo "内核: $(uname -r)" | tee -a $LOG_FILE

echo "" | tee -a $LOG_FILE

# 记录初始状态

echo "初始内存状态:" | tee -a $LOG_FILE

free -h | tee -a $LOG_FILE

echo "" | tee -a $LOG_FILE

while true; do

    TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

    # 1. 基础内存信息

    TOTAL=$(free -m | awk 'NR==2{print $2}')

    USED=$(free -m | awk 'NR==2{print $3}')

    FREE=$(free -m | awk 'NR==2{print $4}')

    AVAILABLE=$(free -m | awk 'NR==2{print $7}')

    BUFFERS=$(free -m | awk 'NR==2{print $6}')

    # 2. swap 信息

    SWAP_TOTAL=$(free -m | awk 'NR==3{print $2}')

    SWAP_USED=$(free -m | awk 'NR==3{print $3}')

    # 3. slab 信息

    SLAB=$(grep "^Slab:" /proc/meminfo | awk '{print $2/1024}')

    SRECLAIMABLE=$(grep "^SReclaimable:" /proc/meminfo | awk '{print $2/1024}')

    SUNRECLAIM=$(grep "^SUnreclaim:" /proc/meminfo | awk '{print $2/1024}')

    # 4. 脏页信息

    DIRTY=$(grep "^Dirty:" /proc/meminfo | awk '{print $2/1024}')

    WRITEBACK=$(grep "^Writeback:" /proc/meminfo | awk '{print $2/1024}')

    # 5. 进程内存 TOP 3

    TOP_PROCS=$(ps aux --sort=-%mem | head -4 | tail -3 | awk '{printf "%s:%dMB ", $11, int($6/1024)}')

    # 6. 记录日志

    printf "%s | Mem: %dM/%dM (Avail:%dM) Swap: %dM/%dM | Slab: %.0fM (SU:%.0fM SR:%.0fM) | Dirty: %.0fM | %s\n" \

        "$TIMESTAMP" "$USED" "$TOTAL" "$AVAILABLE" "$SWAP_USED" "$SWAP_TOTAL" \

        "$SLAB" "$SUNRECLAIM" "$SRECLAIMABLE" "$DIRTY" "$TOP_PROCS" >> $LOG_FILE

    # 7. 检查异常

    ALERT=0

    # 可用内存过低

    if [ $AVAILABLE -lt 500 ]; then

        echo "$TIMESTAMP | ⚠️  WARNING: Low memory - Available: ${AVAILABLE}MB" | tee -a $LOG_FILE

        ALERT=1

    fi

    # swap 使用过高

    if [ $SWAP_TOTAL -gt 0 ] && [ $SWAP_USED -gt $((SWAP_TOTAL / 2)) ]; then

        SWAP_PERCENT=$(awk "BEGIN {printf \"%.1f\", $SWAP_USED * 100 / $SWAP_TOTAL}")

        echo "$TIMESTAMP | ⚠️  WARNING: High swap usage - ${SWAP_PERCENT}%" | tee -a $LOG_FILE

        ALERT=1

    fi

    # SUnreclaim 过高

    if [ $(echo "$SUNRECLAIM > 1000" | bc -l 2>/dev/null || echo 0) -eq 1 ]; then

        echo "$TIMESTAMP | ⚠️  WARNING: High SUnreclaim - ${SUNRECLAIM}MB" | tee -a $LOG_FILE

        ALERT=1

    fi

    # 脏页过多

    if [ $(echo "$DIRTY > 500" | bc -l 2>/dev/null || echo 0) -eq 1 ]; then

        echo "$TIMESTAMP | ⚠️  WARNING: High dirty pages - ${DIRTY}MB" | tee -a $LOG_FILE

        ALERT=1

    fi

    # 如果有告警,记录详细信息

    if [ $ALERT -eq 1 ]; then

        DETAIL_FILE="$LOG_DIR/alert_$(date +%Y%m%d_%H%M%S).log"

        echo "========== 内存告警详情 ==========" > $DETAIL_FILE

        echo "时间: $TIMESTAMP" >> $DETAIL_FILE

        echo "" >> $DETAIL_FILE

        echo "内存详情:" >> $DETAIL_FILE

        free -h >> $DETAIL_FILE

        echo "" >> $DETAIL_FILE

        echo "TOP 10 进程:" >> $DETAIL_FILE

        ps aux --sort=-%mem | head -11 >> $DETAIL_FILE

        echo "" >> $DETAIL_FILE

        echo "TOP 10 slab:" >> $DETAIL_FILE

        sudo cat /proc/slabinfo 2>/dev/null | tail -n +3 | \

            awk '{print $1, $3*$4/1024/1024 "MB"}' | sort -k2 -rn | head -10 >> $DETAIL_FILE

        echo "" >> $DETAIL_FILE

        echo "内存压力:" >> $DETAIL_FILE

        cat /proc/pressure/memory 2>/dev/null >> $DETAIL_FILE || echo "不支持" >> $DETAIL_FILE

        echo "详细报告: $DETAIL_FILE" | tee -a $LOG_FILE

    fi

    sleep $INTERVAL

done

内存趋势分析脚本

#!/bin/bash

# memory_trend_analysis.sh - 内存使用趋势分析

LOG_FILE="/var/log/memory_monitor/memory_$(date +%Y%m%d).log"

if [ ! -f "$LOG_FILE" ]; then

    echo "日志文件不存在: $LOG_FILE"

    exit 1

fi

echo "========== 内存使用趋势分析 =========="

echo "日志文件: $LOG_FILE"

echo "分析时间: $(date)"

echo ""

# 1. 统计信息

TOTAL_LINES=$(grep -c "Mem:" $LOG_FILE)

echo "总记录数: $TOTAL_LINES"

echo ""

# 2. 内存使用趋势

echo "【内存使用趋势】"

grep "Mem:" $LOG_FILE | awk -F'|' '{

    split($2, mem, " ");

    for (i in mem) {

        if (mem[i] ~ /^[0-9]+M\//) {

            split(mem[i], parts, "/");

            used = parts[1];

            gsub(/M/, "", used);

            sum += used;

            count++;

            if (min == 0 || used < min) min = used;

            if (used > max) max = used;

        }

    }

}

END {

    if (count > 0) {

        avg = sum / count;

        printf "平均使用: %.0f MB\n", avg;

        printf "最小使用: %d MB\n", min;

        printf "最大使用: %d MB\n", max;

        printf "波动范围: %d MB\n", max - min;

    }

}'

echo ""

# 3. 可用内存趋势

echo "【可用内存趋势】"

grep "Avail:" $LOG_FILE | awk -F'Avail:' '{

    split($2, parts, "M");

    avail = parts[1];

    sum += avail;

    count++;

    if (min == 0 || avail < min) min = avail;

    if (avail > max) max = avail;

}

END {

    if (count > 0) {

        avg = sum / count;

        printf "平均可用: %.0f MB\n", avg;

        printf "最小可用: %d MB\n", min;

        printf "最大可用: %d MB\n", max;

        if (min < 500) {

            printf "⚠️  警告: 可用内存曾低于 500MB\n";

        }

    }

}'

echo ""

# 4. swap 使用趋势

echo "【swap 使用趋势】"

grep "Swap:" $LOG_FILE | awk -F'Swap:' '{

    split($2, parts, "M/");

    used = parts[1];

    gsub(/ /, "", used);

    sum += used;

    count++;

    if (used > max) max = used;

}

END {

    if (count > 0) {

        avg = sum / count;

        printf "平均使用: %.0f MB\n", avg;

        printf "最大使用: %d MB\n", max;

        if (max > 100) {

            printf "⚠️  警告: swap 使用超过 100MB\n";

        }

    }

}'

echo ""

# 5. SUnreclaim 趋势

echo "【SUnreclaim 趋势】"

grep "SU:" $LOG_FILE | awk -F'SU:' '{

    split($2, parts, "M");

    su = parts[1];

    sum += su;

    count++;

    if (min == 0 || su < min) min = su;

    if (su > max) max = su;

}

END {

    if (count > 0) {

        avg = sum / count;

        printf "平均: %.0f MB\n", avg;

        printf "最小: %.0f MB\n", min;

        printf "最大: %.0f MB\n", max;

        printf "增长: %.0f MB\n", max - min;

        if (max - min > 100) {

            printf "⚠️  警告: SUnreclaim 增长超过 100MB,可能有内核泄漏\n";

        }

    }

}'

echo ""

# 6. 内存泄漏检测

echo "【内存泄漏检测】"

FIRST_USED=$(grep "Mem:" $LOG_FILE | head -1 | awk -F'Mem:' '{split($2, a, "M/"); print a[1]}' | tr -d ' ')

LAST_USED=$(grep "Mem:" $LOG_FILE | tail -1 | awk -F'Mem:' '{split($2, a, "M/"); print a[1]}' | tr -d ' ')

if [ -n "$FIRST_USED" ] && [ -n "$LAST_USED" ]; then

    DIFF=$((LAST_USED - FIRST_USED))

    FIRST_TIME=$(grep "Mem:" $LOG_FILE | head -1 | awk '{print $1, $2}')

    LAST_TIME=$(grep "Mem:" $LOG_FILE | tail -1 | awk '{print $1, $2}')

    echo "首次记录: $FIRST_TIME - ${FIRST_USED}MB"

    echo "最后记录: $LAST_TIME - ${LAST_USED}MB"

    echo "内存增长: ${DIFF}MB"

    if [ $DIFF -gt 500 ]; then

        echo "❌ 严重: 检测到明显的内存增长,可能存在内存泄漏!"

    elif [ $DIFF -gt 200 ]; then

        echo "⚠️  警告: 内存有所增长,建议继续观察"

    else

        echo "✅ 正常: 内存使用稳定"

    fi

fi

echo ""

# 7. TOP 进程分析

echo "【TOP 进程统计】"

grep -oP '(?<=\| )[^|]+$' $LOG_FILE | tr ' ' '\n' | grep ':' | \

    awk -F':' '{proc[$1] += $2} END {for (p in proc) printf "%-30s %10.0f MB\n", p, proc[p]/NR}' | \

    sort -k2 -rn | head -10

echo ""

echo "========== 分析完成 =========="


🔬 内核内存泄漏检测

kmemleak 使用

分析 kmemleak 报告

#!/bin/bash

# analyze_kmemleak.sh - 分析 kmemleak 报告

KMEMLEAK_FILE="/sys/kernel/debug/kmemleak"

if [ ! -f "$KMEMLEAK_FILE" ]; then

    echo "❌ kmemleak 不可用"

    echo "请检查:"

    echo "1. 内核是否支持 CONFIG_DEBUG_KMEMLEAK"

    echo "2. debugfs 是否已挂载"

    exit 1

fi

echo "========== kmemleak 泄漏分析 =========="

echo "时间: $(date)"

echo ""

# 触发扫描

echo "触发 kmemleak 扫描..."

echo scan > $KMEMLEAK_FILE

sleep 10

# 读取报告

REPORT=$(sudo cat $KMEMLEAK_FILE)

if [ -z "$REPORT" ]; then

    echo "✅ 未检测到内存泄漏"

    exit 0

fi

# 统计泄漏对象数量

LEAK_COUNT=$(echo "$REPORT" | grep -c "unreferenced object")

echo "检测到 $LEAK_COUNT 个泄漏对象"

echo ""

# 按大小排序

echo "【按大小排序的泄漏 (TOP 10)】"

echo "$REPORT" | grep "unreferenced object" | \

    awk '{gsub(/[()]/, "", $6); print $4, $6}' | \

    sort -k2 -rn | head -10 | \

    awk '{printf "地址: %s  大小: %s 字节\n", $1, $2}'

echo ""

# 统计总泄漏大小

TOTAL_SIZE=$(echo "$REPORT" | grep "unreferenced object" | \

    awk '{gsub(/[()]/, "", $6); sum += $6} END {print sum}')

TOTAL_MB=$(echo "scale=2; $TOTAL_SIZE / 1024 / 1024" | bc)

echo "总泄漏大小: ${TOTAL_MB} MB"

echo ""

# 按模块分组

echo "【按模块分组】"

echo "$REPORT" | grep -oP '\[\K[^\]]+' | grep -v "^<" | \

    sort | uniq -c | sort -rn | head -10 | \

    awk '{printf "%5d 次  %s\n", $1, $2}'

echo ""

# 按进程分组

echo "【按进程分组】"

echo "$REPORT" | grep "comm" | \

    awk '{gsub(/"/, "", $2); print $2}' | \

    sort | uniq -c | sort -rn | head -10 | \

    awk '{printf "%5d 次  %s\n", $1, $2}'

echo ""

# 按年龄分组

echo "【按年龄分组】"

echo "$REPORT" | grep "age" | \

    awk '{

        age = $NF;

        gsub(/[()]/, "", age);

        gsub(/s/, "", age);

        if (age < 60) bucket = "< 1分钟";

        else if (age < 3600) bucket = "< 1小时";

        else if (age < 86400) bucket = "< 1天";

        else bucket = ">= 1天";

        count[bucket]++;

    }

    END {

        for (b in count) printf "%10s: %d 个对象\n", b, count[b]

    }'

echo ""

# 保存完整报告

REPORT_FILE="/var/log/kmemleak_$(date +%Y%m%d_%H%M%S).log"

echo "$REPORT" > $REPORT_FILE

echo "完整报告已保存到: $REPORT_FILE"

echo ""

# 建议

echo "【建议】"

if [ $LEAK_COUNT -gt 100 ]; then

    echo "❌ 严重: 泄漏对象过多,需要立即处理"

    echo "   1. 检查最近加载的内核模块"

    echo "   2. 查看 backtrace 定位泄漏代码"

    echo "   3. 更新或卸载有问题的驱动"

elif [ $LEAK_COUNT -gt 10 ]; then

    echo "⚠️  警告: 发现一定数量的泄漏"

    echo "   1. 继续监控泄漏增长情况"

    echo "   2. 分析 backtrace 找出泄漏源"

else

    echo "✅ 泄漏数量较少,可能是误报或小问题"

fi

echo ""

echo "========== 分析完成 =========="

使用 ftrace 跟踪内存分配

使用 eBPF/BCC 检测内存泄漏

内核内存泄漏定位流程


👤 用户空间内存泄漏检测

valgrind 使用

# 4. 泄漏类型说明
# definitely lost: 确定泄漏(必须修复)
#   - 分配的内存没有任何指针指向
#   - 无法被释放
#
# indirectly lost: 间接泄漏
#   - 由 definitely lost 导致的泄漏
#   - 修复 definitely lost 后会消失
#
# possibly lost: 可能泄漏
#   - 指针指向内存块的中间
#   - 需要进一步分析
#
# still reachable: 仍可达
#   - 程序结束时未释放但仍有指针指向
#   - 通常不是问题(如全局变量)
#
# suppressed: 被抑制
#   - 使用抑制文件忽略的泄漏

AddressSanitizer (ASan) 使用

# 常用选项:
# detect_leaks=1: 启用泄漏检测
# log_path=file: 输出到文件
# halt_on_error=0: 发现错误后继续运行
# verbosity=1: 详细输出
# 4. 与 valgrind 对比
# ASan 优点:
#   - 运行速度快(2-3倍慢)
#   - 可以检测更多类型的错误
#   - 可以在生产环境使用
#
# ASan 缺点:
#   - 需要重新编译
#   - 内存开销大(2-3倍)

进程内存分析

用户空间泄漏检测脚本

#!/bin/bash

# user_space_leak_detector.sh - 用户空间内存泄漏检测

PROCESS_NAME=$1

INTERVAL=60

THRESHOLD=100  # MB

DURATION=3600  # 监控时长(秒)

if [ -z "$PROCESS_NAME" ]; then

    echo "用法: $0 <进程名>"

    echo "示例: $0 mysqld"

    exit 1

fi

PID=$(pidof $PROCESS_NAME)

if [ -z "$PID" ]; then

    echo "❌ 进程不存在: $PROCESS_NAME"

    exit 1

fi

LOG_FILE="/var/log/leak_${PROCESS_NAME}_$(date +%Y%m%d_%H%M%S).log"

echo "========== 用户空间内存泄漏检测 ==========" | tee -a $LOG_FILE

echo "进程: $PROCESS_NAME (PID: $PID)" | tee -a $LOG_FILE

echo "监控间隔: ${INTERVAL}秒" | tee -a $LOG_FILE

echo "泄漏阈值: ${THRESHOLD}MB" | tee -a $LOG_FILE

echo "监控时长: $((DURATION / 3600))小时" | tee -a $LOG_FILE

echo "" | tee -a $LOG_FILE

# 获取初始内存使用

INITIAL_RSS=$(cat /proc/$PID/status | grep VmRSS | awk '{print $2}')

INITIAL_TIME=$(date +%s)

INITIAL_MB=$((INITIAL_RSS / 1024))

echo "初始 RSS: ${INITIAL_MB}MB" | tee -a $LOG_FILE

echo "" | tee -a $LOG_FILE

ELAPSED=0

while [ $ELAPSED -lt $DURATION ]; do

    sleep $INTERVAL

    ELAPSED=$((ELAPSED + INTERVAL))

    # 检查进程是否还在运行

    if ! kill -0 $PID 2>/dev/null; then

        echo "$(date): ⚠️  进程已退出" | tee -a $LOG_FILE

        exit 0

    fi

    # 获取当前内存使用

    CURRENT_RSS=$(cat /proc/$PID/status | grep VmRSS | awk '{print $2}')

    CURRENT_TIME=$(date +%s)

    CURRENT_MB=$((CURRENT_RSS / 1024))

    # 计算增长

    DIFF_RSS=$((CURRENT_RSS - INITIAL_RSS))

    DIFF_TIME=$((CURRENT_TIME - INITIAL_TIME))

    DIFF_MB=$((DIFF_RSS / 1024))

    # 计算增长率(MB/小时)

    if [ $DIFF_TIME -gt 0 ]; then

        RATE=$(echo "scale=2; $DIFF_MB * 3600 / $DIFF_TIME" | bc)

    else

        RATE=0

    fi

    # 记录日志

    printf "%s | RSS=%dMB (+%dMB) Rate=%.2fMB/h Elapsed=%dmin\n" \

        "$(date '+%Y-%m-%d %H:%M:%S')" "$CURRENT_MB" "$DIFF_MB" "$RATE" "$((ELAPSED / 60))" | \

        tee -a $LOG_FILE

    # 检查是否超过阈值

    if [ $DIFF_MB -gt $THRESHOLD ]; then

        echo "$(date): ⚠️  检测到内存泄漏!" | tee -a $LOG_FILE

        echo "内存增长: ${DIFF_MB}MB" | tee -a $LOG_FILE

        echo "运行时间: $((DIFF_TIME / 3600))小时" | tee -a $LOG_FILE

        echo "增长率: ${RATE}MB/h" | tee -a $LOG_FILE

        echo "" | tee -a $LOG_FILE

        # 保存详细信息

        echo "进程状态:" | tee -a $LOG_FILE

        cat /proc/$PID/status | tee -a $LOG_FILE

        echo "" | tee -a $LOG_FILE

        echo "内存映射 TOP 20:" | tee -a $LOG_FILE

        cat /proc/$PID/smaps | grep -E "^[0-9a-f]|^Size:|^Rss:" | \

            paste - - - | sort -k6 -rn | head -20 | tee -a $LOG_FILE

        echo "" | tee -a $LOG_FILE

        # 如果增长严重,可以选择生成 core dump

        if [ $DIFF_MB -gt $((THRESHOLD * 2)) ]; then

            echo "$(date): ❌ 严重泄漏,生成 core dump" | tee -a $LOG_FILE

            gcore -o /tmp/core_${PROCESS_NAME}_$(date +%Y%m%d_%H%M%S) $PID

        fi

    fi

done

echo "" | tee -a $LOG_FILE

echo "========== 监控完成 ==========" | tee -a $LOG_FILE

echo "最终 RSS: ${CURRENT_MB}MB" | tee -a $LOG_FILE

echo "总增长: ${DIFF_MB}MB" | tee -a $LOG_FILE

echo "平均增长率: ${RATE}MB/h" | tee -a $LOG_FILE

echo "日志文件: $LOG_FILE" | tee -a $LOG_FILE

八、特殊场景内存问题

8.1 网络子系统内存泄漏

conntrack 连接跟踪泄漏

在防火墙、NAT 网关等场景中,conntrack 表满是常见问题:

解决方案:

SKB (Socket Buffer) 泄漏

网络数据包处理中的 SKB 泄漏:

检测脚本:

#!/bin/bash

# skb_leak_detector.sh

echo "========== SKB 泄漏检测 =========="

# 获取初始值

INITIAL_ALLOC=$(cat /proc/net/sockstat | grep TCP | awk '{print $10}')

INITIAL_MEM=$(cat /proc/net/sockstat | grep TCP | awk '{print $12}')

echo "初始 TCP alloc: $INITIAL_ALLOC"

echo "初始 TCP mem: $INITIAL_MEM pages"

echo ""

for i in {1..10}; do

    sleep 60

    CURRENT_ALLOC=$(cat /proc/net/sockstat | grep TCP | awk '{print $10}')

    CURRENT_MEM=$(cat /proc/net/sockstat | grep TCP | awk '{print $12}')

    DIFF_ALLOC=$((CURRENT_ALLOC - INITIAL_ALLOC))

    DIFF_MEM=$((CURRENT_MEM - INITIAL_MEM))

    echo "$(date): alloc=$CURRENT_ALLOC (+$DIFF_ALLOC) mem=$CURRENT_MEM (+$DIFF_MEM pages)"

    if [ $DIFF_MEM -gt 1000 ]; then

        echo "⚠️  检测到 SKB 内存持续增长!"

        echo "检查网络驱动和协议栈是否正常释放 SKB"

    fi

done

8.2 文件系统缓存问题

Page Cache 不释放

问题场景:

C 代码示例:

8.3 容器环境内存问题

Cgroup 内存限制与泄漏

容器内存泄漏检测:

#!/bin/bash

# container_memory_monitor.sh

CONTAINER_ID=$1

THRESHOLD_PERCENT=80

if [ -z "$CONTAINER_ID" ]; then

    echo "用法: $0 <容器ID>"

    exit 1

fi

echo "监控容器: $CONTAINER_ID"

while true; do

    # 获取内存使用情况

    STATS=$(docker stats --no-stream --format "{{.MemUsage}}" $CONTAINER_ID)

    USED=$(echo $STATS | awk '{print $1}' | sed 's/GiB//;s/MiB//')

    LIMIT=$(echo $STATS | awk '{print $3}' | sed 's/GiB//;s/MiB//')

    # 计算使用百分比

    PERCENT=$(docker stats --no-stream --format "{{.MemPerc}}" $CONTAINER_ID | sed 's/%//')

    echo "$(date): 内存使用 $USED / $LIMIT ($PERCENT%)"

    if (( $(echo "$PERCENT > $THRESHOLD_PERCENT" | bc -l) )); then

        echo "⚠️  内存使用超过阈值!"

        # 查看容器内进程内存使用

        echo "容器内 TOP 进程:"

        docker exec $CONTAINER_ID ps aux --sort=-%mem | head -10

        # 检查是否有 OOM 事件

        CGROUP_PATH=$(docker inspect -f '{{.Id}}' $CONTAINER_ID)

        OOM_COUNT=$(cat /sys/fs/cgroup/memory/docker/$CGROUP_PATH/memory.oom_control 2>/dev/null | grep oom_kill | awk '{print $2}')

        echo "OOM 次数: $OOM_COUNT"

    fi

    sleep 60

done

容器内存泄漏排查

容器资源限制最佳实践:

# Docker Compose 示例
version'3'
services:
  webapp:
    imagemyapp:latest
    deploy:
      resources:
        limits:
          memory2G          # 硬限制
          cpus'2'
        reservations:
          memory1G          # 软限制
# 启用 OOM Killer
    oom_kill_disablefalse
# 设置 OOM 分数调整
    oom_score_adj500

Kubernetes 示例:

apiVersionv1
kindPod
metadata:
  namewebapp
spec:
  containers:
  - nameapp
    imagemyapp:latest
    resources:
      requests:
        memory"1Gi"
        cpu"500m"
      limits:
        memory"2Gi"
        cpu"2"
# 存活探针
    livenessProbe:
      httpGet:
        path/health
        port8080
      initialDelaySeconds30
      periodSeconds10

九、Slab 内存分析

9.1 Slab 内存基础

Slab 是内核对象缓存机制,用于高效分配常用内核对象:

9.2 Slab 泄漏检测

检测脚本:

#!/bin/bash

# slab_leak_detector.sh

LOG_FILE="/var/log/slab_leak_$(date +%Y%m%d_%H%M%S).log"

INTERVAL=300  # 5分钟

THRESHOLD=100  # MB

echo "========== Slab 内存泄漏检测 ==========" | tee -a $LOG_FILE

echo "监控间隔: ${INTERVAL}秒" | tee -a $LOG_FILE

echo "泄漏阈值: ${THRESHOLD}MB" | tee -a $LOG_FILE

echo "" | tee -a $LOG_FILE

# 创建临时文件存储初始状态

TEMP_INITIAL="/tmp/slab_initial_$$"

TEMP_CURRENT="/tmp/slab_current_$$"

# 获取初始 slab 使用情况

cat /proc/slabinfo | tail -n +3 | awk '{print $1, $2, $3, $4}' > $TEMP_INITIAL

echo "初始 Slab 使用 TOP 10:" | tee -a $LOG_FILE

cat /proc/slabinfo | tail -n +3 | \

    awk '{printf "%-30s %10d objs %8.2f MB\n", $1, $2, $2*$4/1024/1024}' | \

    sort -k4 -rn | head -10 | tee -a $LOG_FILE

echo "" | tee -a $LOG_FILE

while true; do

    sleep $INTERVAL

    # 获取当前 slab 使用情况

    cat /proc/slabinfo | tail -n +3 | awk '{print $1, $2, $3, $4}' > $TEMP_CURRENT

    echo "$(date '+%Y-%m-%d %H:%M:%S')" | tee -a $LOG_FILE

    echo "----------------------------------------" | tee -a $LOG_FILE

    # 比较变化

    join $TEMP_INITIAL $TEMP_CURRENT | \

    awk '{

        name=$1;

        initial_objs=$2;

        initial_total=$3;

        objsize=$4;

        current_objs=$5;

        current_total=$6;

        diff_objs = current_objs - initial_objs;

        diff_mb = diff_objs * objsize / 1024 / 1024;

        if (diff_mb > 10) {  # 增长超过 10MB

            printf "%-30s: %+10d objs %+8.2f MB (%.2f%%)\n", 

                   name, diff_objs, diff_mb, 

                   (current_objs - initial_objs) * 100.0 / initial_objs;

        }

    }' | sort -k4 -rn | tee -a $LOG_FILE

    # 检查总体 slab 增长

    INITIAL_SLAB=$(cat /proc/meminfo | grep "^Slab:" | awk '{print $2}')

    CURRENT_SLAB=$(cat /proc/meminfo | grep "^Slab:" | awk '{print $2}')

    DIFF_SLAB=$(( (CURRENT_SLAB - INITIAL_SLAB) / 1024 ))

    echo "" | tee -a $LOG_FILE

    echo "总 Slab 内存: $((CURRENT_SLAB / 1024))MB (增长: ${DIFF_SLAB}MB)" | tee -a $LOG_FILE

    if [ $DIFF_SLAB -gt $THRESHOLD ]; then

        echo "⚠️  检测到 Slab 内存泄漏!" | tee -a $LOG_FILE

        # 显示增长最多的 slab

        echo "" | tee -a $LOG_FILE

        echo "增长最多的 Slab 缓存:" | tee -a $LOG_FILE

        join $TEMP_INITIAL $TEMP_CURRENT | \

        awk '{

            name=$1; initial=$2; objsize=$4; current=$5;

            diff = (current - initial) * objsize / 1024 / 1024;

            if (diff > 0) print name, diff "MB";

        }' | sort -k2 -rn | head -5 | tee -a $LOG_FILE

    fi

    echo "" | tee -a $LOG_FILE

done

# 清理

rm -f $TEMP_INITIAL $TEMP_CURRENT

9.3 常见 Slab 泄漏场景

dentry/inode 缓存泄漏

kmalloc 泄漏

buffer_head 泄漏

十、OOM Killer 机制详解

10.1 OOM Killer 工作原理

当系统内存不足时,OOM Killer 会选择并杀死进程以释放内存:

内存分配请求
    ↓
检查可用内存
    ↓
内存不足?
    ↓ 是
尝试回收内存(page cache, swap等)
    ↓
仍然不足?
    ↓ 是
触发 OOM Killer
    ↓
计算每个进程的 oom_score
    ↓
选择 oom_score 最高的进程
    ↓
发送 SIGKILL 信号杀死进程
    ↓
释放内存

10.2 OOM Score 计算

每个进程都有一个 oom_score,分数越高越容易被杀死:

OOM Score 计算因素:

  • 进程使用的内存(RSS + Swap)

  • 进程运行时间(运行时间短的更容易被杀)

  • 进程优先级

  • oom_score_adj 调整值(-1000 到 1000)

10.3 OOM 日志分析

OOM 发生时会在系统日志中留下详细信息:

典型 OOM 日志解析:

关键信息解读:

  • gfp_mask: 内存分配标志

  • order: 请求的内存页面阶数(2^order 个页面)

  • total_vm: 进程虚拟内存总量

  • rss: 进程实际使用的物理内存

  • oom_score_adj: OOM 分数调整值

  • free: 系统剩余内存

10.4 OOM 保护策略

调整 oom_score_adj

配置 OOM Killer 行为

应用层保护

10.5 OOM 预防措施

#!/bin/bash

# oom_prevention.sh - OOM 预防监控

THRESHOLD=90  # 内存使用阈值(百分比)

CHECK_INTERVAL=60

while true; do

    # 获取内存使用百分比

    MEM_PERCENT=$(free | grep Mem | awk '{printf "%.0f", $3/$2 * 100}')

    echo "$(date): 内存使用 ${MEM_PERCENT}%"

    if [ $MEM_PERCENT -gt $THRESHOLD ]; then

        echo "⚠️  内存使用超过阈值!"

        # 1. 记录当前状态

        echo "=== 内存状态 ===" >> /var/log/oom_prevention.log

        free -h >> /var/log/oom_prevention.log

        # 2. 记录 TOP 进程

        echo "=== TOP 内存进程 ===" >> /var/log/oom_prevention.log

        ps aux --sort=-%mem | head -20 >> /var/log/oom_prevention.log

        # 3. 尝试释放缓存

        sync

        echo 1 > /proc/sys/vm/drop_caches

        # 4. 发送告警

        echo "内存使用 ${MEM_PERCENT}% 超过阈值 ${THRESHOLD}%" | \

            mail -s "OOM 预警" admin@example.com

        # 5. 可选:重启占用内存最多的非关键服务

        # systemctl restart some_service

    fi

    sleep $CHECK_INTERVAL

done

十一、内存碎片问题

11.1 内存碎片类型

内存碎片分为外部碎片和内部碎片:

11.2 内存碎片整理

11.3 应用层避免碎片

十二、实战案例分析

案例 1:内核模块内存泄漏

问题现象

某路由器设备运行数天后,slab 内存持续增长:

排查过程

根本原因

分析内核模块代码发现问题:

解决方案

临时缓解措施:

效果

案例 2:长期运行系统的缓慢内存增长

问题现象

某数据采集服务器运行 3 个月后内存使用持续增长:

排查过程

根本原因

代码分析发现文件句柄泄漏:

解决方案

系统层面优化:

效果

十三、预防与监控方案

13.1 开发阶段预防

代码审查关注点

内存管理检查项:
□ 所有 malloc/new 都有对应的 free/delete
□ 使用智能指针(C++)或 RAII 模式
□ 循环中的内存分配是否会累积
□ 是否有内存泄漏检测工具集成(Valgrind, ASan)
□ 缓存是否有大小限制和过期策略
□ 文件句柄、socket 等资源是否正确关闭
□ 异常处理路径是否释放资源
□ 是否有内存使用监控和告警

编译时检查

# ✅ 使用 AddressSanitizer 编译
$ gcc-fsanitize=address -g-o app app.c
# ✅ 使用 LeakSanitizer
$ gcc-fsanitize=leak -g-o app app.c
# ✅ 使用静态分析工具
$ cppcheck--enable=all --inconclusive src/
# ✅ 使用 Clang Static Analyzer
$ scan-buildmake

自动化监控脚本

#!/bin/bash

# comprehensive_memory_monitor.sh - 综合内存监控

INTERVAL=300  # 5分钟

LOG_DIR="/var/log/memory_monitor"

ALERT_EMAIL="admin@example.com"

mkdir -p $LOG_DIR

# 阈值配置

MEM_THRESHOLD=85          # 内存使用率阈值(%)

SLAB_THRESHOLD=30         # Slab 占比阈值(%)

PROCESS_GROWTH_MB=100     # 进程内存增长阈值(MB/小时)

# 初始化进程内存记录

declare -A PROCESS_MEM_INITIAL

declare -A PROCESS_MEM_TIME

log_message() {

    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_DIR/monitor.log

}

check_system_memory() {

    local mem_percent=$(free | grep Mem | awk '{printf "%.0f", $3/$2 * 100}')

    local mem_available=$(free -h | grep Mem | awk '{print $7}')

    log_message "系统内存使用: ${mem_percent}% (可用: ${mem_available})"

    if [ $mem_percent -gt $MEM_THRESHOLD ]; then

        log_message "⚠️  内存使用超过阈值 ${MEM_THRESHOLD}%"

        # 记录详细信息

        free -h > $LOG_DIR/memory_$(date +%Y%m%d_%H%M%S).txt

        ps aux --sort=-%mem | head -20 >> $LOG_DIR/memory_$(date +%Y%m%d_%H%M%S).txt

        # 发送告警

        echo "内存使用 ${mem_percent}% 超过阈值" | \

            mail -s "内存告警 - $(hostname)" $ALERT_EMAIL

        return 1

    fi

    return 0

}

check_slab_memory() {

    local slab_kb=$(cat /proc/meminfo | grep "^Slab:" | awk '{print $2}')

    local total_kb=$(cat /proc/meminfo | grep "^MemTotal:" | awk '{print $2}')

    local slab_percent=$(echo "scale=2; $slab_kb * 100 / $total_kb" | bc)

    log_message "Slab 内存: $((slab_kb / 1024))MB (${slab_percent}%)"

    if (( $(echo "$slab_percent > $SLAB_THRESHOLD" | bc -l) )); then

        log_message "⚠️  Slab 内存占比过高"

        # 记录 TOP slab 使用者

        cat /proc/slabinfo | tail -n +3 | \

            awk '{printf "%-30s %10d objs %8.2f MB\n", $1, $2, $2*$4/1024/1024}' | \

            sort -k4 -rn | head -20 > $LOG_DIR/slabinfo_$(date +%Y%m%d_%H%M%S).txt

        return 1

    fi

    return 0

}

check_process_growth() {

    local current_time=$(date +%s)

    # 检查所有进程

    while read pid comm rss; do

        local key="${pid}_${comm}"

        # 如果是第一次记录

        if [ -z "${PROCESS_MEM_INITIAL[$key]}" ]; then

            PROCESS_MEM_INITIAL[$key]=$rss

            PROCESS_MEM_TIME[$key]=$current_time

            continue

        fi

        # 计算增长

        local initial_rss=${PROCESS_MEM_INITIAL[$key]}

        local initial_time=${PROCESS_MEM_TIME[$key]}

        local diff_rss=$((rss - initial_rss))

        local diff_time=$((current_time - initial_time))

        # 计算增长率(MB/小时)

        if [ $diff_time -gt 0 ]; then

            local growth_rate=$(echo "scale=2; $diff_rss * 3600 / $diff_time / 1024" | bc)

            if (( $(echo "$growth_rate > $PROCESS_GROWTH_MB" | bc -l) )); then

                log_message "⚠️  进程 $comm (PID: $pid) 内存增长 ${growth_rate}MB/h"

                # 记录进程详情

                echo "=== 进程 $pid ($comm) ===" >> $LOG_DIR/process_growth.log

                cat /proc/$pid/status >> $LOG_DIR/process_growth.log 2>/dev/null

                echo "" >> $LOG_DIR/process_growth.log

            fi

        fi

    done < <(ps -eo pid,comm,rss --no-headers | awk '$3 > 102400')  # 只检查 >100MB 的进程

}

check_oom_events() {

    local oom_count=$(dmesg | grep -c "Out of memory")

    if [ $oom_count -gt 0 ]; then

        log_message "⚠️  检测到 $oom_count 次 OOM 事件"

        dmesg | grep -A 20 "Out of memory" | tail -50 > $LOG_DIR/oom_$(date +%Y%m%d_%H%M%S).log

    fi

}

# 主循环

log_message "========== 内存监控启动 =========="

while true; do

    check_system_memory

    check_slab_memory

    check_process_growth

    check_oom_events

    sleep $INTERVAL

done

13.2 日志分析

#!/bin/bash

# analyze_memory_logs.sh - 分析内存日志

LOG_FILE="/var/log/memory_monitor/monitor.log"

echo "========== 内存日志分析 =========="

echo ""

# 1. 统计告警次数

echo "=== 告警统计 ==="

echo "内存告警次数: $(grep -c "内存使用超过阈值" $LOG_FILE)"

echo "Slab 告警次数: $(grep -c "Slab 内存占比过高" $LOG_FILE)"

echo "进程增长告警: $(grep -c "进程.*内存增长" $LOG_FILE)"

echo "OOM 事件: $(grep -c "检测到.*OOM" $LOG_FILE)"

echo ""

# 2. 找出内存增长最快的进程

echo "=== 内存增长最快的进程 ==="

grep "进程.*内存增长" $LOG_FILE | \

    awk '{print $(NF-1), $(NF-3)}' | \

    sort -k1 -rn | head -10

echo ""

# 3. 分析内存使用趋势

echo "=== 内存使用趋势(最近 24 小时)==="

grep "系统内存使用" $LOG_FILE | tail -288 | \  # 24h * 60min / 5min

    awk '{print $1, $2, $4}' | \

    awk -F'%' '{print $1}' | \

    awk '{sum+=$NF; count++} END {print "平均:", sum/count "%"}'

echo ""

# 4. 生成报告

REPORT_FILE="/var/log/memory_monitor/report_$(date +%Y%m%d).txt"

{

    echo "内存监控报告 - $(date)"

    echo "======================================"

    echo ""

    echo "告警统计:"

    echo "  内存告警: $(grep -c "内存使用超过阈值" $LOG_FILE)"

    echo "  Slab 告警: $(grep -c "Slab 内存占比过高" $LOG_FILE)"

    echo "  OOM 事件: $(grep -c "检测到.*OOM" $LOG_FILE)"

    echo ""

    echo "问题进程:"

    grep "进程.*内存增长" $LOG_FILE | tail -20

} > $REPORT_FILE

echo "报告已生成: $REPORT_FILE"

十四、常见问题解答(FAQ)

Q1: 如何区分内存泄漏和正常的内存增长?

正常内存增长特征:

  • 增长后趋于稳定

  • 有明确的业务原因(如缓存、连接池)

  • 可以通过释放缓存回收

内存泄漏特征:

  • 持续线性增长,不会稳定

  • 无法通过正常手段回收

  • 最终导致 OOM

判断方法:

Q2: buff/cache 占用很高是否正常?

完全正常。Linux 会使用空闲内存作为文件缓存(page cache)来提升性能。

只有当 available 很低时才需要担心。

Q3: 如何快速定位是哪个进程导致的内存泄漏?

Q4: 内核模块泄漏如何排查?

# 1. 启用 kmemleak
$ mount  -t debugfs nodev /sys/kernel/debug
$ echo  scan > /sys/kernel/debug/kmemleak
$ cat  /sys/kernel/debug/kmemleak
# 2. 检查 slab 使用
$ cat  /proc/slabinfo | sort -k3 -rn | head -20
# 3. 使用 ftrace 追踪内核内存分配
$ cd  /sys/kernel/debug/tracing
$ echo  function > current_tracer
$ echo  kmalloc > set_ftrace_filter
$ echo  1 > tracing_on
$ cat  trace

Q5: 容器被 OOM Kill 但看起来内存还有剩余?

这是因为容器有 cgroup 内存限制:

Q6: 为什么执行 drop_caches 后内存还是很高?

drop_caches 只能释放 page cache、dentries 和 inodes,不能释放:

  • 进程使用的内存(RSS)

  • Slab 中不可回收的部分(SUnreclaim)

  • 共享内存

  • 内核模块占用的内存

Q7: 如何设置合理的 oom_score_adj?

Q8: 内存碎片化严重如何处理?

# 1. 检查碎片化程度
$ cat  /proc/buddyinfo
$ cat  /sys/kernel/debug/extfrag/extfrag_index
# 2. 手动整理内存
$ echo 1 > /proc/sys/vm/compact_memory
# 3. 配置自动整理
$ sysctl -w vm.compaction_proactiveness=20
# 4. 使用大页内存
$ echo  1024 > /proc/sys/vm/nr_hugepages
# 5. 应用层使用内存池避免碎片

Q9: 如何在生产环境安全地排查内存问题?

十五、总结

核心要点

内存问题排查的关键在于:

  1. 快速定位问题类型

    • 用户空间泄漏 → 使用 Valgrind、ASan、进程监控

    • 内核空间泄漏 → 使用 kmemleak、slab 分析

    • 缓存问题 → 检查 page cache、slab

    • OOM 问题 → 分析日志、调整策略

  2. 系统化的排查流程

    • 症状识别 → 工具检测 → 根因分析 → 修复验证

  3. 预防胜于治疗

    • 代码审查和静态分析

    • 编译时检查(ASan、LSan)

    • 单元测试覆盖内存场景

    • 生产环境持续监控

  4. 工具选择

    • 开发阶段:Valgrind、ASan、静态分析

    • 测试阶段:压力测试、长时间运行测试

    • 生产环境:轻量级监控、eBPF、日志分析

最佳实践

// ✅ 内存管理黄金法则
1.谁分配谁释放
2.使用RAII或智能指针
3.避免裸指针传递所有权
4.异常安全的资源管理
5.缓存必须有界和过期
6.定期审查和测试

工具速查表

场景推荐工具命令示例
快速检查系统内存free, topfree -h
查看进程内存ps, smemps aux --sort=-%mem
用户空间泄漏检测Valgrindvalgrind --leak-check=full ./app
内核空间泄漏检测kmemleakcat /sys/kernel/debug/kmemleak
Slab 分析slabinfocat /proc/slabinfo
OOM 日志分析dmesgdmesg \| grep -i oom
容器内存监控docker statsdocker stats --no-stream
Java 堆分析jmap, MATjmap -dump:file=heap.bin <pid>
实时追踪eBPF/BCCmemleak -p <pid>

参考资源

  • Linux 内核文档:Documentation/vm/

  • Valgrind 用户手册:https://valgrind.org/docs/manual/

  • eBPF/BCC 工具集:https://github.com/iovisor/bcc

  • Java 内存分析:Eclipse MAT

  • 容器监控:Prometheus + Grafana


    内存问题的解决不是一蹴而就的,需要持续的监控、分析和优化。保持对系统内存使用的敏感度,在问题变严重之前及时发现和处理,是保障系统稳定运行的关键。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-04-20 20:37:47 HTTP/2.0 GET : https://f.mffb.com.cn/a/484626.html
  2. 运行时间 : 0.092311s [ 吞吐率:10.83req/s ] 内存消耗:5,078.51kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=dd1b8e7cd5a44e52f98bac7891accf46
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000581s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000608s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000260s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000258s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000535s ]
  6. SELECT * FROM `set` [ RunTime:0.000173s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000661s ]
  8. SELECT * FROM `article` WHERE `id` = 484626 LIMIT 1 [ RunTime:0.000535s ]
  9. UPDATE `article` SET `lasttime` = 1776688667 WHERE `id` = 484626 [ RunTime:0.006662s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000237s ]
  11. SELECT * FROM `article` WHERE `id` < 484626 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000646s ]
  12. SELECT * FROM `article` WHERE `id` > 484626 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000357s ]
  13. SELECT * FROM `article` WHERE `id` < 484626 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002218s ]
  14. SELECT * FROM `article` WHERE `id` < 484626 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.005453s ]
  15. SELECT * FROM `article` WHERE `id` < 484626 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.002677s ]
0.093964s