记一次服务器内存硬件故障导致的不定时宕机

问题背景

公司一台运行 MySQL 8.0 的物理服务器(Dell PowerEdge R740xd,128GB DDR4 ECC 内存),作为生产环境的主库。该机器上线约 18 个月,之前从未出现过硬件问题。

故障现象

7 月初开始,这台 MySQL 服务器出现不定时宕机——平均每 2-3 天一次,时间毫无规律:一次是凌晨 3:00,一次是下午 2:30,一次是上午 10:15。宕机后服务器完全无响应,Ping 不通,只能通过 iDRAC 远程控制台强制重启。

每次宕机后检查系统日志:

1
2
$ journalctl -b -1 --no-pager | tail -50
-- Reboot --

宕机前的日志中没有任何异常记录——没有 OOM Killer,没有 kernel panic 堆栈(默认不输出到串口),没有硬件错误的 edac 报告。系统像是被直接拔了电源一样,没有任何临终遗言。

排查过程

第一轮:怀疑温度和电源

通过 iDRAC 查看系统事件日志(SEL):

1
2
3
4
5
SEL Record:
  Date/Time: 2023-07-10 02:58:14
  Sensor: CPU1 Temp
  Type: Temperature
  Description: Upper Non-Critical going high (85°C)

CPU 温度确实偏高(85°C),但还在正常运行范围内(Tcase max 约 95°C)。清理了服务器内部灰尘并更换了散热硅脂后,CPU 温度降到 65°C——但宕机仍然发生。

第二轮:怀疑内核崩溃(kdump 无输出)

配置 kdump 来捕捉内核崩溃时的内存转储:

1
2
yum install kexec-tools
systemctl start kdump

下一次宕机后检查 /var/crash/——kdump 没有生成任何转储文件。这说明崩溃的类型非常底层,连内核的 crashkernel 都无法正常加载。

第三轮:启用 MCE 详细日志

怀疑是硬件层面的错误触发,在 /etc/default/grub 中添加内核参数:

1
GRUB_CMDLINE_LINUX="... mce=3 mcelog=1 console=ttyS0,115200"

通过 iDRAC 的串口重定向功能捕获下一次宕机时的输出。一周后再次宕机,iDRAC 串口日志中终于抓到了关键信息:

1
2
3
4
5
[Hardware Error]: CPU:0 (7-86-6) MC0_STATUS[-|CE|MiscV|AddrV|-|-|CECC]: 0x9c20400001080136
[Hardware Error]: Error Addr: 0x00000006f3c82540
[Hardware Error]: MC0 Error: ECC error at CPU:0, channel:1, DIMM: A2
[Hardware Error]: cache level: L2, tx: GEN, mem-tx: RD
Kernel panic - not syncing: Fatal machine check on current CPU

Machine Check Exception (MCE)——CPU 检测到了无法纠正的 ECC 内存错误(Uncorrectable ECC Error),触发了内核 Panic。

关键信息:

  • 错误位置:CPU:0, Channel:1, DIMM: A2
  • 错误类型:ECC 不可纠正错误
  • 错误地址:0x00000006f3c82540(刚好落在 MySQL 的 buffer pool 内存区域)

第四轮:确认内存故障模式

虽然 ECC 内存能纠正单比特错误,但当同一个字节出现超过 1 个比特错误时就超过了 ECC 的纠错能力,触发不可纠正错误。而这种偶发性多比特错误通常意味着内存条即将彻底损坏。

1
2
3
4
5
# 之前的edac日志其实有单比特可纠正错误的记录,只是没触发MCE
$ grep -i "corrected error" /var/log/messages | grep "DIMM A2"
Jul 03 05:12:14 server kernel: EDAC MC0: 1 CE memory read error on CPU:0 channel:1 slot:A2
Jul 03 19:44:32 server kernel: EDAC MC0: 1 CE memory read error on CPU:0 channel:1 slot:A2
Jul 05 11:37:05 server kernel: EDAC MC0: 1 CE memory read error on CPU:0 channel:1 slot:A2

DIMM A2 早在 7 月 3 日就开始出现可纠正错误(CE)——只是没人关注 edac 日志。CE 累积到无法纠正时就变成了 MCE 导致宕机。

解决方案

  1. 停机更换内存:联系 Dell 售后,确认 DIMM A2 故障,申请 RMA 更换
  2. 更换后验证:通过 memtest86+ 对新内存条做全量检测(pass > 3 次)
  3. 重启应用:确认 MySQL 恢复正常,buffer pool 完整性校验通过

更换内存条后,服务器恢复稳定运行,至今未再宕机。

根因分析

直接原因:DIMM A2 内存条硬件老化导致偶发性不可纠正的 ECC 错误,触发 MCE,内核 Panic 使系统直接宕机。kdump 无法捕获 MCE 级别的 Panic 因为内核已经在极端底层崩溃。

深层原因:可纠正错误(CE)的 edac 日志没有被纳入监控告警体系,内存条在"带病工作"了一周后才演变为不可纠正错误导致宕机。

预防措施

  1. EDAC 监控告警:通过 Zabbix 监控 /sys/devices/system/edac/mc/mc*/ce_count,单条 DIMM 的 CE 数量 >10 即告警
  2. iDRAC 告警集成:将 Dell iDRAC 的 SNMP Trap 接入监控系统,硬件可纠正错误立即触发
  3. 定期硬件巡检:每季度对所有服务器的 SEL 日志和 ECC 统计做一次全面巡检
  4. 建立硬件故障响应流程:CE 告警 → 24 小时内确认 → 48 小时内安排更换窗口
  5. 关键服务冗余:MySQL 主库升级为主从架构,让单机故障不至于导致完全不可用

总结

硬件故障不是"会不会发生"的问题,而是"什么时候发生"的问题。ECC 内存的可纠正错误(CE)是硬件健康的"矿工金丝雀"——当它开始频繁出现时,意味着那条内存条离彻底损坏不远了。这次故障的教训不是 ECC 不够强,而是 CE 的 edac 日志沉默了一整周而没有人关注。在运维中,比监控"已经宕机"更重要的是监控"即将宕机"的信号。

使用 Hugo 构建
主题 StackJimmy 设计