Короткий ответ

AVHDX — overlay. Текущие блоки гостя часто живут в самом новом differencing-файле. Цель — штатный Merge-VHD / добить checkpoint, чтобы VM снова ссылалась на один VHDX. Ручное удаление любого файла цепочки = дырки в диске гостя.

Снимите карту ParentPath от листа к корню, убедитесь что VM Off и никто не держит файлы, сделайте копию всей папки, затем merge от самого дочернего к родителю — как в документации Merge-VHD, не «все сразу».

Симптомы и как отличить

Типичная картина:

  • Get-VHD на текущем диске VM: VhdType : Differencing, ParentPath заполнен;
  • ошибка broken chain при Start-VM;
  • после сбоя backup два recovery overlay;
  • StorageJob Merge в Failed.

Отличия:

Что видноКуда
GUI Delete ещё должен работатьcheckpoint не удаляется
Файл просто lockVHDX не подключается
Backup держит VSSзависание backup
Merge живой но вечный из-за IOнагрузка диска

Возможные причины

  1. Не хватило места, merge оборвался, конфиг VM уже смотрит не туда.
  2. Переименовали/переместили родителя в Explorer.
  3. Одновременно backup, replica и ручной checkpoint.
  4. Подключили средний avhdx как диск VM.
  5. Смешали merge GUI и Merge-VHD.
  6. Антивирус открыл файл на запись посередине.

Диагностика

Get-VM -Name 'VM-APP01' | Format-List State, Id, Path
Get-VMHardDiskDrive -VMName 'VM-APP01' | Format-Table Path, ControllerType
Get-VMCheckpoint -VMName 'VM-APP01' | Format-Table Name, SnapshotType, Path

Карта цепочки (повторите для каждого avhdx):

$leaf = (Get-VMHardDiskDrive -VMName 'VM-APP01').Path | Select-Object -First 1
$cur = $leaf
while ($cur) {
  $h = Get-VHD -Path $cur
  [pscustomobject]@{ Path = $h.Path; Type = $h.VhdType; Parent = $h.ParentPath; FileGB = [math]::Round($h.FileSize/1GB,2) }
  $cur = $h.ParentPath
}
Test-VHD -Path $leaf

Если Get-VHD на ParentPath бросает «cannot find», цепочка порвана: ищите файл по имени в backup/Volume Shadow, не создавайте пустой VHDX с тем же именем.

Get-StorageJob -ErrorAction SilentlyContinue
Get-ClusterSharedVolume
Get-Volume | Format-Table DriveLetter, FileSystemLabel, SizeRemaining

Решение

Сценарий A. Дерево checkpoint целое

Не ходите в Merge-VHD. Вернитесь к Remove-VMCheckpoint. Эта статья — когда GUI/cmdlet снимка уже не могут.

Сценарий B. VM Off, цепочка целая, GUI мёртв

  1. Скопируйте каталог C:\ClusterStorage\Volume1\VM-APP01 на другой том (все vhdx/avhdx/xml).
  2. Отключите диск от VM (настройки SCSI), чтобы Path не держал файл, либо оставьте Off и работайте осторожно: Merge-VHD требует, чтобы целевые файлы не были в exclusive use другой VM.
Stop-VM -Name 'VM-APP01'
# снимите диск из конфигурации только если Merge-VHD ругается на in use
  1. Слейте лист в родителя. Пример: текущий диск data.avhdx, родитель data.vhdx:
Merge-VHD -Path 'C:\ClusterStorage\Volume1\VM-APP01\VM-APP01.avhdx' -DestinationPath 'C:\ClusterStorage\Volume1\VM-APP01\VM-APP01.vhdx'

-DestinationPath должен быть непосредственным родителем этого avhdx, не «самый нижний файл, который вспомнили». Для длинной цепочки повторяйте от листа к корню по одному шагу, каждый раз проверяя Get-VHD.

  1. Верните Path VM на получившийся VHDX:
Get-VMHardDiskDrive -VMName 'VM-APP01' |
  Set-VMHardDiskDrive -Path 'C:\ClusterStorage\Volume1\VM-APP01\VM-APP01.vhdx'
Start-VM -Name 'VM-APP01'

Сценарий C. Обрыв ParentPath

Восстановите недостающий файл из backup в тот же путь, что ждёт ParentPath, либо Set-VHD -Path leaf -ParentPath 'D:\restored\parent.vhdx' только если это действительно тот родитель (тот же идентификатор цепочки). Угадывание родителя по размеру файла — порча.

Сценарий D. Два overlay от backup

Оставьте VM Off. Разберите, какой avhdx сейчас в Get-VMHardDiskDrive. Лишние recovery, на которые никто не ссылается (ни VM, ни ParentPath), можно убрать после доказательства, что на них нет ссылок — и то лучше оставить в архиве заявки.

Сценарий E. Merge-VHD падает на месте

Нет места, lock, read-only. Снимите Read-only, исключите антивирус на время окна, освободите CSV. Не -Force из примеров форумов, если не понимаете параметр вашей версии.

Как проверить, что проблема устранена

Test-VHD -Path 'C:\ClusterStorage\Volume1\VM-APP01\VM-APP01.vhdx'
Get-VHD -Path 'C:\ClusterStorage\Volume1\VM-APP01\VM-APP01.vhdx' | Format-List VhdType, ParentPath, FileSize
Get-VMHardDiskDrive -VMName 'VM-APP01'
Get-VM -Name 'VM-APP01' | Format-List State

ParentPath пуст, Test-VHD без ошибки, гость грузится, приложения видят свежие данные (не откат на дату снимка). Сверьте дату файлов в госте.

Если не помогло

  • После merge старые данные: вы слили не тот лист — откат к копии каталога, сделанной до Merge-VHD.
  • VM не стартует: диск и старт.
  • Экспорт всё ещё видит дерево: экспорт.
  • Цепочка на ReFS/CSV в redirected: сначала storage health.

Не используйте сторонние «VHDX repair» на единственной копии.

Профилактика

  • Не трогать avhdx руками.
  • Не копить снимки.
  • Backup job обязан завершать Hyper-V checkpoint.
  • Перед ручным Merge-VHD — копия цепочки и окно простоя.
  • Документировать Path диска в заявке до любой операции.

FAQ

Чем Merge-VHD отличается от Remove-VMCheckpoint?

Remove знает дерево снимков Hyper-V (XML, память, конфиг). Merge-VHD сливает только два VHD. После ручного merge конфиг VM и checkpoint metadata могут разъехаться — поэтому это аварийный путь.

Можно ли merge при Running?

Живой merge делает сам Hyper-V через checkpoint API. Ручной Merge-VHD — для Offline дисков. Не смешивайте.

DestinationPath — это куда «результат»?

Для Merge-VHD это родитель, в которого вливается дочерний. Дочерний после успеха обычно становится ненужным overlay. Проверьте документацию вашей версии и Get-VHD после операции, прежде чем удалять исходный avhdx.

Set-VHD -IgnoreIdMismatch?

Это когда сознательно подставляют родителя с другим ID. На прод почти всегда запрещено. Ломает связь differencing.

Нужен ли Convert-VHD вместо merge?

Convert копирует цепочку в новый плоский диск. Нужно много места. Запасной путь, если merge нестабилен и есть куда писать.

Почему Test-VHD зелёный, а гость BSOD?

Цепочка файлов валидна, но вы подключили не тот лист (старый avhdx). Смотрите Path в VM, не «какой файл больше».