Azure跨恢复库还原SQL备份时遇Restore-AzRecoveryServicesBackupItem输入无效错误
我正在编写PowerShell脚本,用于从Azure的一个恢复服务库(Recovery Vault)向另一个恢复服务库还原SQL数据库备份项,核心脚本如下:
#modules and variables import-module Az $Sub = "MyAzureSubscription" $RsvSource = "MySourceRecoveryVault" $RsvTarget = "MyTargetRecoveryVault" $SubContext = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" $SourceDB = "SourceDB" $TargetDB = "TargetDB" $SQLTargetInstance = "instance" $SQLTargetServer = "SQLServer" #Get Backup item from Azure RSV Connect-AzAccount -Identity -Subscription $Sub Set-AzContext -subscription $SubContext $SourceVault = Get-AzRecoveryServicesVault | Where-Object { $_.name -eq $RsvSource } $TargetVault = Get-AzRecoveryServicesVault | Where-Object { $_.name -eq $RsvTarget } Set-AzRecoveryServicesVaultContext -Vault $SourceVault $BackupItem = Get-AzRecoveryServicesBackupItem -BackupManagementType AzureWorkload -WorkloadType MSSQL -VaultId $SourceVault.ID | Where-Object { ($_.Name -match $SourceDB ) } #Get Point in time $PointInTime = Get-Date -Date "12/1/2023" -format MM/dd/yyyy #Get Parameters $Container = Get-AzRecoveryServicesBackupContainer -ContainerType AzureVMAppContainer -VaultId $($TargetVault.id) | Where-Object {$_.ServerName -eq "$SQLTargetServer" -and $_.HealthStatus -eq 'Healthy'} $TargetInstance = Get-AzRecoveryServicesBackupProtectableItem -WorkloadType MSSQL -ItemType SQLInstance -ServerName "$SQLTargetServer" -VaultId $($TargetVault.id) $PointBackup = Get-AzRecoveryServicesBackupRecoveryPoint -Item $BackupItem | Where-object { $_.RecoveryPointTime -match $PointInTime } # Configuration $AnotherInstanceWithFullConfig = Get-AzRecoveryServicesBackupWorkloadRecoveryConfig -PointInTime $($PointBackup.RecoveryPointTime) -Item $BackupItem -TargetItem $SQLTargetInstance -Targetcontainer $Container -AlternateWorkloadRestore -VaultId $($SourceVault.ID) $AnotherInstanceWithFullConfig.OverwriteWLIfpresent = "yes" $AnotherInstanceWithFullConfig.RestoredDBName = $TargetDB $AnotherInstanceWithFullConfig.targetPhysicalPath[0].TargetPath = ($AnotherInstanceWithFullConfig.targetPhysicalPath[0].TargetPath) -replace (($AnotherInstanceWithFullConfig.targetPhysicalPath[0].TargetPath | split-path -leaf), "$TargetDB).mdf") $AnotherInstanceWithFullConfig.targetPhysicalPath[1].TargetPath = ($AnotherInstanceWithFullConfig.targetPhysicalPath[1].TargetPath) | ForEach-Object { $_ -replace (($AnotherInstanceWithFullConfig.targetPhysicalPath[1].TargetPath | split-path -leaf), "$TargetDB.ldf") -replace "I:", "L:" } #restore $restore = Restore-AzRecoveryServicesBackupItem -WLRecoveryConfig $AnotherInstanceWithFullConfig -VaultId $($TargetVault.id)
执行脚本时触发以下错误:
Restore-AzRecoveryServicesBackupItem : The User input provided for the call is invalid. Please check the required inputs
我怀疑问题出在$AnotherInstanceWithFullConfig配置上,执行$AnotherInstanceWithFullConfig | Format-list后输出如下:
TargetServer : SQLServer.domain
TargetInstance : instance
RestoredDBName : TargetDB
TargetVirtualMachineId : /subscriptions/xxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/RSGXXXXXXXXXXXX/providers/Microsoft.Compute/virtualMachines/SQLServer
OverwriteWLIfpresent : yes
NoRecoveryMode : Disabled
targetPhysicalPath : {Name_Data, Name_log}
ContainerId : /subscriptions/xxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/RSGXXXXXXXXX/providers/Microsoft.RecoveryServices/vaults/RSVXXXXXXXXXX/backupFabrics/Azure/protectionContainers/vmappcontainer;compute;rsgxxxxxxxx;SQlserver
FullRP :
SourceResourceId : /subscriptions/xxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/RSGXXXXXXXXXXX/providers/Microsoft.Compute/virtualMachines/SQLServer
RestoreRequestType : Alternate WL Restore to diff item
RecoveryPoint : Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlets.Models.AzureWorkloadRecoveryPoint
PointInTime : 12/1/2023 12:04:51 PM
RecoveryMode :
FilePath :
排查思路
修复物理路径替换的语法错误:脚本中替换MDF文件路径时存在语法错误,
"$TargetDB).mdf"多了一个右括号,正确写法应为"$TargetDB.mdf"。错误的路径格式会导致还原请求的输入参数无效。# 修正后的MDF路径替换代码 $AnotherInstanceWithFullConfig.targetPhysicalPath[0].TargetPath = ($AnotherInstanceWithFullConfig.targetPhysicalPath[0].TargetPath) -replace (($AnotherInstanceWithFullConfig.targetPhysicalPath[0].TargetPath | split-path -leaf), "$TargetDB.mdf")显式设置RecoveryMode参数:从配置输出可见
RecoveryMode为空,这是SQL还原的必填参数,需根据需求设置为Recovery(还原后数据库可读写)或NoRecovery(还原后数据库处于还原状态,可继续追加日志备份):$AnotherInstanceWithFullConfig.RecoveryMode = "Recovery"使用正确的TargetItem对象:原脚本中
Get-AzRecoveryServicesBackupWorkloadRecoveryConfig的-TargetItem参数传递的是字符串$SQLTargetInstance,但该参数需要传入Get-AzRecoveryServicesBackupProtectableItem返回的对象,应修改为:$AnotherInstanceWithFullConfig = Get-AzRecoveryServicesBackupWorkloadRecoveryConfig -PointInTime $($PointBackup.RecoveryPointTime) -Item $BackupItem -TargetItem $TargetInstance -Targetcontainer $Container -AlternateWorkloadRestore -VaultId $($SourceVault.ID)验证恢复点的有效性:检查
$PointBackup是否正确获取到了目标恢复点。原脚本使用-match匹配日期可能存在格式问题,建议改用日期对象直接比较:$PointInTime = Get-Date -Date "12/1/2023" $PointBackup = Get-AzRecoveryServicesBackupRecoveryPoint -Item $BackupItem | Where-Object { $_.RecoveryPointTime.Date -eq $PointInTime.Date }确保
$PointBackup不为空,且是有效的恢复点对象。检查跨Vault权限:确认执行脚本的托管身份(Managed Identity)同时拥有源恢复服务库和目标恢复服务库的权限,至少需要
Recovery Services Contributor以及目标SQL虚拟机的SQL Contributor权限。验证容器ID的一致性:配置输出中
ContainerId里的服务器名是SQlserver(大小写混合),而目标服务器名为SQLServer,虽然Azure大部分场景不区分大小写,但建议确保$Container获取的是完全匹配的健康容器,避免因大小写问题导致的容器识别错误。
内容的提问来源于stack exchange,提问作者UltraPS

