SQL Powershell:删除-SqlAvailabilityDatabase
SQL Powershell: Remove-SqlAvailabilityDatabase
我正在编写一个 Powershell 脚本来在高可用性环境中备份和恢复数据库(一切都需要使用 SMO 完成)。这包括几个步骤(或多或少:从主服务器上的可用性组中删除数据库,删除辅助服务器上的数据库,创建备份,恢复备份,再次添加数据库)。
脚本在其中一台数据库服务器上执行时 运行 运行良好。但现在我必须 运行 它在 Management/Application 服务器上。这现在给了我几个新问题...
与服务器的连接工作正常。
然后我从可用性组读取所有数据库:
$Global:ProdKopieDatabases = $server.AvailabilityGroups[$Global:ProdKopieAvailabailityGroup].AvailabilityDatabases
如果我检查 $ProdKopieDatabases,它会准确显示我期望的数据库数量。它也是 Microsoft.SqlServer.Management.Smo.AvailabilityDatabase
类型的对象
在脚本的下方,我需要从可用性组中删除数据库
foreach($DatabaseToRemove in $Global:ProdKopieDatabases)
{
try
{
Remove-SqlAvailabilityDatabase -InputObject $Global:ProdKopieDatabases[$DatabaseToRemove.Name.ToString()] -ErrorAction Stop
#Remove-SqlAvailabilityDatabase -Path $($Private:MyAgPrimaryPath + "\AvailabilityDatabases\" + $DatabaseToRemove.Name.ToString()) -ErrorAction Stop
Start-Sleep -Seconds 5
Write-Host .. OK.
}
catch
{
Log-Write ($Error[0].ToString())
Return 1
}
}
如果我在第一个 foreach 之前检查 $Global:ProdKopieDatabases 变量,我会看到所有数据库(即 3)。但是在 Remove-SqlAvailabilityDatabase 之后,已经从组中删除的数据库也从 $Global:ProdKopieDatabases 变量中删除了。因此,当 foreach 进入第二轮时,我得到一个错误:
Error: Collection was modified; enumeration operation may not execute.
我不明白为什么?好像变量 "by reference" 已连接到可用性数据库。如果是这个原因,我该如何更改?
如果我尝试将它添加到另一个变量并仅使用 $c,甚至会发生这种情况:
$c = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityDatabase #$Global:ProdKopieDatabases
$c = $Global:ProdKopieDatabases | Select *
当我直接在 SQL 服务器上 运行 运行脚本时,我可以通过以下方式完成
$Private:MyAgPrimaryPath = "SQLSERVER:\SQL$PrimaryServer\DEFAULT\AvailabilityGroups$Global:ProdKopieAvailabailityGroup"
$Global:ProdKopieDatabases = dir $Private:MyAgPrimaryPath\AvailabilityDatabases
foreach 相同,但 remove 不同:
Remove-SqlAvailabilityDatabase -Path $($Private:MyAgPrimaryPath + "\AvailabilityDatabases\" + $DatabaseToRemove.Name.ToString()) -ErrorAction Stop
执行此 Remove-SqlAvailabilityDatabase 命令后,变量 $Global:ProdKopieDatabases 中仍然包含所有数据库...
我完全不知道了。我理解错误信息,但我不明白为什么变量也被改变了..
非常感谢任何帮助!
提前致谢
我找到了一个 solution/workaround...(很丑)
首先我填写变量:
$Global:ProdKopieDatabases = $server.AvailabilityGroups[$Global:ProdKopieAvailabailityGroup].AvailabilityDatabases
然后在 foreach 之前,我创建了一个新变量,其中只有名称:
$c = $Global:ProdKopieDatabases | Select Name
我让 foreach 运行 覆盖新创建的变量,对于 -InputObject,我每次重新确定对象...
foreach($DatabaseToRemove in $c)
{
try
{
Remove-SqlAvailabilityDatabase -InputObject $server.AvailabilityGroups[$Global:ProdKopieAvailabailityGroup].AvailabilityDatabases[$DatabaseToRemove.Name.ToString()] -ErrorAction Stop
Start-Sleep -Seconds 2
}
catch
{
$Error[0] | Format-List -Force
Return 1
}
}
在脚本的下方,我只使用 $c
变量,不再使用 $Global:
...
也许有一天我会明白为什么我的 $Global:
变量会那样。直到现在,我都不知道...
希望这篇 post 有一天能对某些人有所帮助 ;-)
我正在编写一个 Powershell 脚本来在高可用性环境中备份和恢复数据库(一切都需要使用 SMO 完成)。这包括几个步骤(或多或少:从主服务器上的可用性组中删除数据库,删除辅助服务器上的数据库,创建备份,恢复备份,再次添加数据库)。
脚本在其中一台数据库服务器上执行时 运行 运行良好。但现在我必须 运行 它在 Management/Application 服务器上。这现在给了我几个新问题...
与服务器的连接工作正常。 然后我从可用性组读取所有数据库:
$Global:ProdKopieDatabases = $server.AvailabilityGroups[$Global:ProdKopieAvailabailityGroup].AvailabilityDatabases
如果我检查 $ProdKopieDatabases,它会准确显示我期望的数据库数量。它也是 Microsoft.SqlServer.Management.Smo.AvailabilityDatabase
类型的对象在脚本的下方,我需要从可用性组中删除数据库
foreach($DatabaseToRemove in $Global:ProdKopieDatabases)
{
try
{
Remove-SqlAvailabilityDatabase -InputObject $Global:ProdKopieDatabases[$DatabaseToRemove.Name.ToString()] -ErrorAction Stop
#Remove-SqlAvailabilityDatabase -Path $($Private:MyAgPrimaryPath + "\AvailabilityDatabases\" + $DatabaseToRemove.Name.ToString()) -ErrorAction Stop
Start-Sleep -Seconds 5
Write-Host .. OK.
}
catch
{
Log-Write ($Error[0].ToString())
Return 1
}
}
如果我在第一个 foreach 之前检查 $Global:ProdKopieDatabases 变量,我会看到所有数据库(即 3)。但是在 Remove-SqlAvailabilityDatabase 之后,已经从组中删除的数据库也从 $Global:ProdKopieDatabases 变量中删除了。因此,当 foreach 进入第二轮时,我得到一个错误:
Error: Collection was modified; enumeration operation may not execute.
我不明白为什么?好像变量 "by reference" 已连接到可用性数据库。如果是这个原因,我该如何更改?
如果我尝试将它添加到另一个变量并仅使用 $c,甚至会发生这种情况:
$c = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityDatabase #$Global:ProdKopieDatabases
$c = $Global:ProdKopieDatabases | Select *
当我直接在 SQL 服务器上 运行 运行脚本时,我可以通过以下方式完成
$Private:MyAgPrimaryPath = "SQLSERVER:\SQL$PrimaryServer\DEFAULT\AvailabilityGroups$Global:ProdKopieAvailabailityGroup"
$Global:ProdKopieDatabases = dir $Private:MyAgPrimaryPath\AvailabilityDatabases
foreach 相同,但 remove 不同:
Remove-SqlAvailabilityDatabase -Path $($Private:MyAgPrimaryPath + "\AvailabilityDatabases\" + $DatabaseToRemove.Name.ToString()) -ErrorAction Stop
执行此 Remove-SqlAvailabilityDatabase 命令后,变量 $Global:ProdKopieDatabases 中仍然包含所有数据库...
我完全不知道了。我理解错误信息,但我不明白为什么变量也被改变了..
非常感谢任何帮助!
提前致谢
我找到了一个 solution/workaround...(很丑)
首先我填写变量:
$Global:ProdKopieDatabases = $server.AvailabilityGroups[$Global:ProdKopieAvailabailityGroup].AvailabilityDatabases
然后在 foreach 之前,我创建了一个新变量,其中只有名称:
$c = $Global:ProdKopieDatabases | Select Name
我让 foreach 运行 覆盖新创建的变量,对于 -InputObject,我每次重新确定对象...
foreach($DatabaseToRemove in $c)
{
try
{
Remove-SqlAvailabilityDatabase -InputObject $server.AvailabilityGroups[$Global:ProdKopieAvailabailityGroup].AvailabilityDatabases[$DatabaseToRemove.Name.ToString()] -ErrorAction Stop
Start-Sleep -Seconds 2
}
catch
{
$Error[0] | Format-List -Force
Return 1
}
}
在脚本的下方,我只使用 $c
变量,不再使用 $Global:
...
也许有一天我会明白为什么我的 $Global:
变量会那样。直到现在,我都不知道...
希望这篇 post 有一天能对某些人有所帮助 ;-)