Hyper-V的虚拟硬盘VHDX文件过大超过虚拟机本身大小很多时排查和处理方法

迅恒数据中心
这几天Hyper-V搞了虚拟机搭建一个Windwos下的PHP网站环境,安装了几个CMS做测试,测试完几个网站后发现Hyper-V虚拟机的虚拟硬盘VHDX文件从11GB涨到了100GB,而虚拟机中看虚拟机系统和数据占用大小才11G左右,和宿主机中VHDX大小差距很大。
后面通过测试是因为PHP运行临时文件、session缓存、PHP建站大量碎片化随机读写引起的。
最核心元凶:VHDX 默认32MB 块大小 + PHP 建站大量碎片化随机读写
VHDX 动态磁盘默认块大小=32MB,这是爆炸式膨胀的根本原因。
规则:只要虚拟机向任意 4KB 扇区写入一次,Hyper-V 会一次性给宿主机分配完整32MB物理块,哪怕只写了几 KB 网页文件、日志、临时缓存。
在安装多个 PHP CMS 会产生海量零散小写入:
1. PHP 运行临时文件、session 缓存、上传临时目录;
2. Mysql/MariaDB 数据库碎片化写入、日志滚动;
3. IIS 日志、PHP 错误日志、网站缓存文件大量细碎读写;
4. CMS 解压安装包、后台生成缩略图、配置文件频繁改写。
举例:往虚拟硬盘写入 1KB 配置文件,宿主机直接吃掉 32MB;重复修改几十次同类小文件,轻松累积几十个 GB,最终堆到100GB。
虚拟机内文件系统只会统计真实有效文件 11G,但宿主机统计所有曾经分配过的32MB大块,二者出现巨大断层。

出现该问题时解决方法:
1、清理PHP网站缓存文件和修改网站缓存策略
如易优eyoucms的data\runtime\cache清理其中的缓存文件
和修改application\config.php中的缓存配置过期时间
具体教程参考https://www.piis.cn/zhishi/2848.html
2、虚拟机内操作:
fsutil behavior query DisableDeleteNotify
看是否为0
不是请改之:
fsutil behavior set DisableDeleteNotify 0
3、虚拟机整理磁盘碎片:
defrag C: /O /L /H /U
defrag D: /O /L /H /U
defrag E: /O /L /H /U
defrag F: /O /L /H /U
defrag G: /O /L /H /U
清理PHP网站缓存后回收块效果如下

4、宿主机Hyper-V虚拟机管理中对虚拟硬盘进行压缩回收
5、宿主机(母机)长期预防杜绝下次建站再次爆涨(只适合新建VHDX时操作):
新建VHDX手动指定BlockSize=1MB,而不是默认 32MB
New-VHD -Path D:\vm.vhdx -SizeBytes 1.5TB -Dynamic -BlockSizeBytes 1MB

分类:教程帮助 百度收录 必应收录