<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>内存回收 on Zero Day Notes</title>
        <link>https://blog.5772447.xyz/tags/%E5%86%85%E5%AD%98%E5%9B%9E%E6%94%B6/</link>
        <description>Recent content in 内存回收 on Zero Day Notes</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Thu, 15 Oct 2026 09:00:00 +0800</lastBuildDate><atom:link href="https://blog.5772447.xyz/tags/%E5%86%85%E5%AD%98%E5%9B%9E%E6%94%B6/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>Hyper-V 动态内存回收：业务虚拟机为何准点变慢</title>
            <link>https://blog.5772447.xyz/posts/b6bc4810/</link>
            <pubDate>Thu, 15 Oct 2026 09:00:00 +0800</pubDate>
            <guid>https://blog.5772447.xyz/posts/b6bc4810/</guid>
            <description>&lt;h2 id=&#34;问题背景&#34;&gt;&lt;a href=&#34;#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;分公司部署了一套 Hyper-V 虚拟化平台：一台宿主机（Windows Server 2022，64GB 内存）承载 8 台虚机——ERP 应用、ERP 数据库（SQL Server）、域控、文件服务、报表服务、备份服务等。当初为提升部署密度，除域控外大部分虚机都开启了动态内存（Dynamic Memory），让空闲虚机把暂时用不到的内存&amp;quot;还&amp;quot;给宿主机。&lt;/p&gt;&#xA;&lt;p&gt;平台平稳运行一年多。最近两周，ERP 用户开始集中反馈：每天上午 10 点左右系统&amp;quot;准点变卡&amp;quot;，单据保存转圈、报表查询超时，持续 20~30 分钟后自行恢复；偶尔下午 14:30 也来一波。运维重启过应用、查过网络，都没有效果，而时间点雷打不动。&lt;/p&gt;&#xA;&lt;h2 id=&#34;故障现象&#34;&gt;&lt;a href=&#34;#%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;故障现象&#xD;&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;ERP 系统每天上午 10:00~10:30、部分下午 14:30 前后响应明显变慢，过后自愈。&lt;/li&gt;&#xA;&lt;li&gt;虚机内的 SQL Server 无慢查询堆积、无锁等待异常；宿主 CPU 使用率不到 40%。&lt;/li&gt;&#xA;&lt;li&gt;性能计数器显示：故障时段 SQL 的 Page Life Expectancy（PLE）从 8000 秒级骤降到 200 秒以下，磁盘读 IOPS 飙升，等待类型以 PAGEIOLATCH_SH（等待数据页从磁盘读入）为主。&lt;/li&gt;&#xA;&lt;li&gt;症状集中在 ERP，同宿主的文件服务、域控基本无感。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;排查过程&#34;&gt;&lt;a href=&#34;#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;第一步，先排除数据库自身问题。&lt;/strong&gt; 拆解慢查询、锁等待、执行计划，都正常；但 PLE 骤降指向一个明确的方向——缓冲池里的数据页被大规模清了出去，查询只能全部落到磁盘。SQL Server 不会无缘无故清自己的缓存，那就是&amp;quot;内存被谁拿走了&amp;quot;。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第二步，对齐时间线。&lt;/strong&gt; 上午 10:00 是备份服务虚机执行增量备份的时间；下午 14:30 是报表服务生成日报的时间。两者都是内存消耗大户，与&amp;quot;准点变卡&amp;quot;的时间点完全重合。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第三步，到宿主机上看内存账本。&lt;/strong&gt; 在 Hyper-V 宿主机上用 PowerShell 取样：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Get-VM | Select-Object Name, MemoryAssigned, MemoryDemand&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;对比 9:50（正常）与 10:10（故障）两组数据：ERP 数据库虚机的 MemoryAssigned 从 12GB 掉到 2GB 出头——恰好贴着它设置的&amp;quot;最小内存&amp;quot;2GB；而 MemoryDemand 仍有 6GB 多。同一时段，备份虚机的 MemoryAssigned 从 4GB 涨到 12GB。宿主机物理内存 64GB，而 8 台虚机的最大内存之和是 96GB——超配了 1.5 倍。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第四步，弄清回收机制。&lt;/strong&gt; 动态内存的工作原理是：宿主机内存充足时按需求给虚机分配，内存紧张时均衡器从各虚机回收内存（通过虚机内的 balloon 驱动），被回收的虚机立即感受到内存压力。谁被回收得多，取决于内存需求读数与内存权重。ERP 数据库虚机的&amp;quot;最小内存&amp;quot;当初随手设成了 2GB，意味着回收的下限可以低到 2GB；而它的内存需求读数在数据库负载下并不总是&amp;quot;高&amp;quot;——缓冲池里放着大量看似&amp;quot;闲置&amp;quot;的缓存页。于是每次宿主内存紧张，它都首当其冲被&amp;quot;瘦身&amp;quot;。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第五步，验证因果。&lt;/strong&gt; 把备份任务临时改到凌晨执行，次日 ERP 全天未再卡顿；再手动在宿主上触发一次内存压力测试，ERP 虚机的 MemoryAssigned 立刻下跌、PLE 同步跳水。链路闭环。&lt;/p&gt;&#xA;&lt;h2 id=&#34;解决方案&#34;&gt;&lt;a href=&#34;#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;解决方案&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;先错峰&lt;/strong&gt;：备份服务改到 23:00 执行、日报生成改到 12:30，当天生效，短期止血。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;核心整改&lt;/strong&gt;：ERP 数据库虚机改为静态内存（关机后取消动态内存，固定 16GB）。微软对 Hyper-V 上运行 SQL Server 使用动态内存是支持的，但也强调必须把内存参数配置得当；考虑到这台库是分公司命脉，我们评估后选择固定分配，把不确定性从生产库上拿掉。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;配置修正&lt;/strong&gt;：其余保留动态内存的虚机，把&amp;quot;最小内存&amp;quot;统一提到合理水位（不低于日常峰值的 70%），并给关键虚机调整内存权重，让均衡器在回收时有优先级可循。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;容量治理&lt;/strong&gt;：复核宿主机超配比，把 96GB/64GB（1.5 倍）收敛到 1.2 倍以内；同步规划内存扩容或虚机迁出。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;监控补齐&lt;/strong&gt;：SQL 的 PLE、宿主内存可用量、虚机 MemoryAssigned 与需求差值，接入监控并设阈值告警。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;根因分析&#34;&gt;&lt;a href=&#34;#%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;直接根因是宿主机内存超配叠加动态内存的回收机制：每天备份、报表任务在固定时间点申请大量内存，宿主内存紧张，均衡器从&amp;quot;需求读数偏低、最小内存设得随意&amp;quot;的 ERP 数据库虚机回收内存，SQL 缓冲池被清空，查询全部转为物理读，表现为&amp;quot;准点变慢、过后自愈&amp;quot;。&lt;/p&gt;&#xA;&lt;p&gt;更深一层，是把&amp;quot;提升部署密度&amp;quot;的手段（动态内存加超配）用在了最不该省的负载上：数据库的性能几乎等价于它持有的内存，动态内存在宿主压力下回收内存的行为，对应用服务器只是一次性能波动，对数据库却是缓冲池清空、IO 雪崩。基础设施的每一分&amp;quot;省&amp;quot;，最终都由业务在每天上午十点准时买单。&lt;/p&gt;&#xA;&lt;h2 id=&#34;预防措施&#34;&gt;&lt;a href=&#34;#%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;数据库、缓存等内存敏感负载的虚机一律使用静态内存，不参与动态回收；&lt;/li&gt;&#xA;&lt;li&gt;启用动态内存的虚机必须显式设置合理的最小内存与内存权重，并在变更评审中说明理由；&lt;/li&gt;&#xA;&lt;li&gt;宿主机内存超配比纳入容量基线（建议不超过 1.2 倍），新增虚机前先算总账；&lt;/li&gt;&#xA;&lt;li&gt;关键性能指标（PLE、宿主可用内存、虚机内存回收量）接入监控告警；&lt;/li&gt;&#xA;&lt;li&gt;定时任务（备份、报表）排期时把宿主内存峰值纳入考量，避免与业务高峰叠加。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;总结&#34;&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&amp;ldquo;准点变慢&amp;quot;四个字，把排错方向从&amp;quot;系统坏了&amp;quot;直接掰到了&amp;quot;有人在准点做某件事&amp;rdquo;。最终定位到的不是一条故障链，而是一本资源账：超配的宿主、被低估的最小内存、固定时间的任务高峰，三者叠加，每天上演一次。虚拟化让资源&amp;quot;弹性&amp;quot;，但不代表可以不给关键负载定底线——动态内存是压缩成本的好工具，但它的前提是：别把命脉放在可以被回收的位置上。&lt;/p&gt;&#xA;&lt;h2 id=&#34;延伸阅读&#34;&gt;&lt;a href=&#34;#%e5%bb%b6%e4%bc%b8%e9%98%85%e8%af%bb&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;延伸阅读&#xD;&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.5772447.xyz/posts/3ac611a9/&#34; &gt;Hyper-V 虚拟机实时迁移失败：vSwitch 配置漂移&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.5772447.xyz/posts/3d6d8adf/&#34; &gt;Hyper-V VHDX 异常膨胀：40GB 差异磁盘残留清理&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.5772447.xyz/posts/42fcb7d3/&#34; &gt;记一次服务器内存硬件故障导致的不定时宕机&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
        </item></channel>
</rss>
