适用对象:DM 实例出现"隔一段时间崩一次"“日志戛然而止”“凌晨固定时间挂”,含内核 OOM 与达梦自 halt 两种死法
排查前先给死亡方式分类,两类死法的取证方向完全不同:
| 死亡方式 | 日志特征 | 谁杀的 | 取证重点 |
|---|---|---|---|
| A. 静默死亡 | 日志戛然而止,无任何 ERROR/FATAL | Linux 内核 OOM killer(SIGKILL,不可捕获) | 内核日志 /var/log/messages、journalctl -k |
| B. 自报崩溃 | 日志写满 [FATAL],并生成 dmhalt_*.dump |
达梦自身内存分配失败 → dm_sys_halt |
达梦日志 FATAL 块 + dmhalt dump |
关键结论(本案例):两类死法同源 —— 主机物理内存 + swap 被同时打满,达梦是"最大的住户",不是"原因"。
现象
↓ ① 分类死法:有无 FATAL?有无 dmhalt?
↓ ② DB 侧:最后一条日志是什么?前后有无线程风暴?
↓ ③ 内核侧:OOM 记录是否与 DB 日志同秒?Kill 了谁?score 多少?
↓ ④ 内存账:物理内存多大?swap 用了多少?谁占最多(anon-rss)?
↓ ⑤ 配额墙:ulimit / cgroup / systemd 是否设了限制?(常见误判方向)
↓ ⑥ 触发器:谁在固定时间制造压力?(crontab / 定时任务 / 同步工具)
↓ ⑦ 结论:容量问题 or 调度问题 or 二者叠加
时序对齐是第一原则:内核日志时间戳与达梦日志时间戳必须能对上。若 dmesg -T 与 messages 偏移,以 messages/journalctl 为准。
| # | 方向 | 要回答的问题 | 关键命令/文件 |
|---|---|---|---|
| 1 | 死法分类 | 有没有 FATAL / dmhalt? | tail、grep FATAL、ls dmhalt_* |
| 2 | 崩溃时刻的 DB 现场 | 崩前几秒发生了什么? | sed -n 'X,Yp' 定位崩溃前 N 行 |
| 3 | 线程/连接风暴 | 是否突发大量连接? | grep dthrd_info_add |
| 4 | 内核 OOM | 谁触发、杀了谁、score? | journalctl -k、awk '/oom-killer/,/reaped/' |
| 5 | 内存账 | 物理/swap 余量、内存大户 | free -h、swapon --show、ps aux --sort=-%mem |
| 6 | 配额墙排除 | 是否进程级限制? | /proc/$PID/limits、cgroup、ulimit -a |
| 7 | 定时触发源 | 为什么总在凌晨同一时刻? | crontab -l、/etc/cron.d/、systemctl list-timers、任务脚本 |
# 进程最后几条日志(判断"有声/无声"死亡)
tail -5 /soft/dmdbms/log/dm_DMSERVER_202609.log
tail -20 /soft/dmdbms/log/dm_DMSERVER_*.log
# 事件1:FATAL 块
sed -n '18580,18601p' /soft/dmdbms/log/dm_DMSERVER_1_202609.log
# 崩溃前 16 秒现场
sed -n '202300,202313p' /soft/dmdbms/log/dm_DMSERVER_202609.log
# dmhalt 崩溃转储(自 halt 才有)
ls -l /soft/dmdbms/log/dmhalt_*
cat /soft/dmdbms/log/dmhalt_DMSERVER_1_24613_202609005_021027.dump
# 线程风暴量化:看线程号跳变速度
grep "dthrd_info_add" /soft/dmdbms/log/dm_*.log | tail -30
dmesg -T | grep -iE "oom|killed process|reaped"
journalctl -k --since "2026-09-05 01:20" --until "2026-09-05 01:35" | grep -iE "oom|killed"
# 完整 OOM 段(从触发者到 reaper 回收目标进程)
awk '/dm_sql_thd invoked oom-killer/,/oom_reaper: reaped process 16254/' /var/log/messages \
| grep -A15 "Killed process"
# 内存耗尽细节(swap 是否为 0、物理内存多大)
awk '/dm_sql_thd invoked oom-killer/,/oom_reaper: reaped process 16254/' /var/log/messages \
| grep -E "Free swap|Total swap|Mem-Info"
# 崩溃瞬间"谁在吃内存"(Tasks 表 = 内存大户排行)
awk '/oom-killer/,/oom_reaper: reaped process/' /var/log/messages | grep -A60 "Tasks state"
free -h swapon --show ps aux --sort=-%mem | head -15 ps -eo pid,ppid,rss,comm --sort=-rss | head -20
PID=$(pgrep -x dmserver | head -1); cat /proc/$PID/limits
cat /sys/fs/cgroup/memory/*/memory.limit_in_bytes
systemctl cat DmServiceDMSERVER_1 | grep -iE "limit|memory"
su - dmdba -c 'ulimit -a'
判读:出现 Max address space unlimited / cgroup limit ≈ 无限制 / systemd 无 MemoryMax → 不存在可调的"内存墙",调 ulimit 无效,问题在整机内存总量。
crontab -l # root
crontab -l -u dmdba
ls /etc/cron.d/; systemctl list-timers
cat /soft/D3/YD03.sh # 看有没有 for 循环 + 行尾 & 并发
grep -n "&" /soft/D3/YD03.sh # 并发点最常见的写法
达梦侧定时作业(需 SYSDBA):
SELECT * FROM SYSJOB.SYSJOBS; -- 若报 -2103 无效模式名,说明库未建作业系统,任务在应用侧
date; timedatectl; date -r /soft/dmdbms/log/dmhalt_*.dump
tail -5 看最后一条:有明显 FATAL → 路径 B(自 halt);戛然而止无报错 → 路径 A(内核 OOM)。ls /soft/dmdbms/log/dmhalt_*:有 dump 说明是路径 B。/var/log/messages 或 journalctl -k 里按崩溃时刻 ±5 分钟搜 oom|Killed process。XXX invoked oom-killer)、杀了谁(Killed process <pid> (dmserver) score N)、触发者身份(本例 dm_sql_thd 是达梦连接线程、AWT-XAWT 是 Java 图形线程 → 直指 DataX JVM)。Free swap = 0kB、物理内存大小 → 确认"整机耗尽"而非"进程超限"。mem_malloc_ex2(2097208) out of memory!, fail to allocate memory from OS.
[for dem]SYSTEM SHUTDOWN ABORT.
pthread_create error in os_thread_create with errno 11
code = -1, dm_sys_halt now!!!
grep dthrd_info_add 看线程创建节奏:本例 16 秒新建约 5000 线程(T4517 → T9531)→ 典型连接风暴。cat /proc/<dmserver>/limits + cgroup + systemd 一起看,确认无 MemoryMax。crontab、/etc/cron.d/、systemctl list-timers。& = 一次性并发拉起 N 个任务(本例 YD03.sh 约 150 张表 → 150 个 DataX JVM)。&,或 xargs -P4 限流 ≤4,或拆时段执行;DataX "speed":{"channel":1},调小 JVM -Xms/-Xmx。Dm_restart.sh 文件不存在(每天静默失败)→ 改 systemd Restart=on-failure 托管。oom-killer|Out of memory 关键字 + 进程存活探活 + swap 水位告警。dm.ini(BUFFER / MAX_SESSIONS)合计内存预算。| 现象 | 指向 | 下一步 |
|---|---|---|
| 日志戛然而止、无任何报错 | 内核 SIGKILL | 查内核 OOM 日志 |
有 FATAL + dm_sys_halt + dmhalt dump |
达梦自 halt | 读 FATAL 块与 dump |
mem_malloc_ex2(...) out of memory! 连 2MB 都失败 |
整机内存/swap 耗尽 | 排除配额墙后查谁吃光 |
pthread_create ... errno 11 |
线程创建失败(EAGAIN,也是资源耗尽) | 同上 |
崩前 dthrd_info_add 密度剧增 |
连接风暴 | 找外部批量任务 |
invoked oom-killer 是 java 线程(AWT-XAWT 等) |
Java 进程群触发 | 查 DataX/同步工具 |
Free swap = 0kB |
swap 耗尽 | 整机容量问题 |
/proc/<pid>/limits 全 unlimited |
非配额墙 | 别再调 ulimit |
| 崩溃时间集中在固定时刻 | 定时任务 | 审计 crontab 与脚本并发 |
Dm_restart.sh 不存在 |
自动拉起从未生效 | 改 systemd 托管 |
白天 free 显示很空 |
尖峰被监控漏掉 | 用秒级/分钟级采集或历史 sar |
dmserver 当内存元凶 → 本案 168 上 dmserver 仅 ~300MB(anon-rss 298560kB);要看是谁触发的 OOM。ulimit/cgroup 当解释 → 本案实测全 unlimited,调它无效。dmesg -T 时间戳直接采信 → 存在内核时间偏移,需与 messages/journalctl 对齐后再定案。文章
阅读量
获赞
