Hyper-V 动态内存回收:业务虚拟机为何准点变慢

ERP 每天上午准点变慢,根因是 Hyper-V 宿主机内存超配下动态内存回收压缩了数据库虚机的缓冲池。错峰备份任务、核心库改静态内存并补齐监控后恢复。

问题背景

分公司部署了一套 Hyper-V 虚拟化平台:一台宿主机(Windows Server 2022,64GB 内存)承载 8 台虚机——ERP 应用、ERP 数据库(SQL Server)、域控、文件服务、报表服务、备份服务等。当初为提升部署密度,除域控外大部分虚机都开启了动态内存(Dynamic Memory),让空闲虚机把暂时用不到的内存"还"给宿主机。

平台平稳运行一年多。最近两周,ERP 用户开始集中反馈:每天上午 10 点左右系统"准点变卡",单据保存转圈、报表查询超时,持续 20~30 分钟后自行恢复;偶尔下午 14:30 也来一波。运维重启过应用、查过网络,都没有效果,而时间点雷打不动。

故障现象

  • ERP 系统每天上午 10:00~10:30、部分下午 14:30 前后响应明显变慢,过后自愈。
  • 虚机内的 SQL Server 无慢查询堆积、无锁等待异常;宿主 CPU 使用率不到 40%。
  • 性能计数器显示:故障时段 SQL 的 Page Life Expectancy(PLE)从 8000 秒级骤降到 200 秒以下,磁盘读 IOPS 飙升,等待类型以 PAGEIOLATCH_SH(等待数据页从磁盘读入)为主。
  • 症状集中在 ERP,同宿主的文件服务、域控基本无感。

排查过程

第一步,先排除数据库自身问题。 拆解慢查询、锁等待、执行计划,都正常;但 PLE 骤降指向一个明确的方向——缓冲池里的数据页被大规模清了出去,查询只能全部落到磁盘。SQL Server 不会无缘无故清自己的缓存,那就是"内存被谁拿走了"。

第二步,对齐时间线。 上午 10:00 是备份服务虚机执行增量备份的时间;下午 14:30 是报表服务生成日报的时间。两者都是内存消耗大户,与"准点变卡"的时间点完全重合。

第三步,到宿主机上看内存账本。 在 Hyper-V 宿主机上用 PowerShell 取样:

1
Get-VM | Select-Object Name, MemoryAssigned, MemoryDemand

对比 9:50(正常)与 10:10(故障)两组数据:ERP 数据库虚机的 MemoryAssigned 从 12GB 掉到 2GB 出头——恰好贴着它设置的"最小内存"2GB;而 MemoryDemand 仍有 6GB 多。同一时段,备份虚机的 MemoryAssigned 从 4GB 涨到 12GB。宿主机物理内存 64GB,而 8 台虚机的最大内存之和是 96GB——超配了 1.5 倍。

第四步,弄清回收机制。 动态内存的工作原理是:宿主机内存充足时按需求给虚机分配,内存紧张时均衡器从各虚机回收内存(通过虚机内的 balloon 驱动),被回收的虚机立即感受到内存压力。谁被回收得多,取决于内存需求读数与内存权重。ERP 数据库虚机的"最小内存"当初随手设成了 2GB,意味着回收的下限可以低到 2GB;而它的内存需求读数在数据库负载下并不总是"高"——缓冲池里放着大量看似"闲置"的缓存页。于是每次宿主内存紧张,它都首当其冲被"瘦身"。

第五步,验证因果。 把备份任务临时改到凌晨执行,次日 ERP 全天未再卡顿;再手动在宿主上触发一次内存压力测试,ERP 虚机的 MemoryAssigned 立刻下跌、PLE 同步跳水。链路闭环。

解决方案

  1. 先错峰:备份服务改到 23:00 执行、日报生成改到 12:30,当天生效,短期止血。
  2. 核心整改:ERP 数据库虚机改为静态内存(关机后取消动态内存,固定 16GB)。微软对 Hyper-V 上运行 SQL Server 使用动态内存是支持的,但也强调必须把内存参数配置得当;考虑到这台库是分公司命脉,我们评估后选择固定分配,把不确定性从生产库上拿掉。
  3. 配置修正:其余保留动态内存的虚机,把"最小内存"统一提到合理水位(不低于日常峰值的 70%),并给关键虚机调整内存权重,让均衡器在回收时有优先级可循。
  4. 容量治理:复核宿主机超配比,把 96GB/64GB(1.5 倍)收敛到 1.2 倍以内;同步规划内存扩容或虚机迁出。
  5. 监控补齐:SQL 的 PLE、宿主内存可用量、虚机 MemoryAssigned 与需求差值,接入监控并设阈值告警。

根因分析

直接根因是宿主机内存超配叠加动态内存的回收机制:每天备份、报表任务在固定时间点申请大量内存,宿主内存紧张,均衡器从"需求读数偏低、最小内存设得随意"的 ERP 数据库虚机回收内存,SQL 缓冲池被清空,查询全部转为物理读,表现为"准点变慢、过后自愈"。

更深一层,是把"提升部署密度"的手段(动态内存加超配)用在了最不该省的负载上:数据库的性能几乎等价于它持有的内存,动态内存在宿主压力下回收内存的行为,对应用服务器只是一次性能波动,对数据库却是缓冲池清空、IO 雪崩。基础设施的每一分"省",最终都由业务在每天上午十点准时买单。

预防措施

  • 数据库、缓存等内存敏感负载的虚机一律使用静态内存,不参与动态回收;
  • 启用动态内存的虚机必须显式设置合理的最小内存与内存权重,并在变更评审中说明理由;
  • 宿主机内存超配比纳入容量基线(建议不超过 1.2 倍),新增虚机前先算总账;
  • 关键性能指标(PLE、宿主可用内存、虚机内存回收量)接入监控告警;
  • 定时任务(备份、报表)排期时把宿主内存峰值纳入考量,避免与业务高峰叠加。

总结

“准点变慢"四个字,把排错方向从"系统坏了"直接掰到了"有人在准点做某件事”。最终定位到的不是一条故障链,而是一本资源账:超配的宿主、被低估的最小内存、固定时间的任务高峰,三者叠加,每天上演一次。虚拟化让资源"弹性",但不代表可以不给关键负载定底线——动态内存是压缩成本的好工具,但它的前提是:别把命脉放在可以被回收的位置上。

延伸阅读

使用 Hugo 构建
主题 Stack 由 Jimmy 设计