Public/Invoke-mssRemoveDatabaseFromAvailabilityGroup.TempPoint.ps1
|
<#
.SYNOPSIS Entfernt eine oder mehrere Datenbanken aus ihrer Always On-Verfügbarkeitsgruppe. .DESCRIPTION Die Funktion erkennt selbstständig, in welcher Verfügbarkeitsgruppe sich die angegebene Datenbank befindet, entfernt sie daraus und löscht sie anschließend von allen sekundären Replikaten. Systemdatenbanken werden ignoriert. Wenn kein SqlInstance-Parameter angegeben wird, wird standardmäßig der aktuelle Computername ($env:COMPUTERNAME) verwendet. .PARAMETER SqlInstance Die primäre SQL Server-Instanz (das primäre Replikat der AG). Standard: aktueller Computername. .PARAMETER SqlCredential Alternative Anmeldeinformationen. .PARAMETER Database Name oder Array von Benutzerdatenbanken, die aus ihrer AG entfernt werden sollen. Wird ignoriert, wenn -All gesetzt ist. .PARAMETER All Wenn gesetzt, werden alle Benutzerdatenbanken, die Mitglied einer AG sind, entfernt. .PARAMETER EnableException Schalter, um Ausnahmen durchzulassen. .PARAMETER Confirm Fordert vor kritischen Aktionen (Entfernen aus AG, Löschen auf Secondaries) eine Bestätigung an. .PARAMETER WhatIf Zeigt, was passieren würde, ohne Änderungen durchzuführen. .EXAMPLE # Einzelne Datenbank aus ihrer AG entfernen Remove-mssDatabaseFromAvailabilityGroup -Database "SalesDB" .EXAMPLE # Alle AG-Datenbanken entfernen Remove-mssDatabaseFromAvailabilityGroup -All .NOTES Erfordert dbatools und Invoke-mssLogging. #> function Remove-mssDatabaseFromAvailabilityGroup { [CmdletBinding(DefaultParameterSetName = 'Specific', SupportsShouldProcess = $true, ConfirmImpact = 'None')] param ( [Parameter(Mandatory = $false, Position = 0)] [string]$SqlInstance, [Parameter(Mandatory = $false)] [System.Management.Automation.PSCredential]$SqlCredential, [Parameter(Mandatory = $false, ParameterSetName = 'Specific')] [string[]]$Database, [Parameter(Mandatory = $false, ParameterSetName = 'All')] [switch]$All, [Parameter(Mandatory = $false)] [switch]$EnableException ) begin { $functionName = $MyInvocation.MyCommand.Name if (-not $PSBoundParameters.ContainsKey('SqlInstance') -or [string]::IsNullOrWhiteSpace($SqlInstance)) { $SqlInstance = $env:COMPUTERNAME } if (-not (Get-Module -ListAvailable -Name dbatools)) { throw "dbatools-Modul nicht gefunden." } Invoke-mssLogging -Message "Starte $functionName auf $SqlInstance" -FunctionName $functionName -Level "INFO" $results = @() } process { try { # Alle Verfügbarkeitsgruppen abrufen $agParams = @{ SqlInstance = $SqlInstance; SqlCredential = $SqlCredential; ErrorAction = 'Stop' } if ($EnableException) { $agParams.EnableException = $true } $allAGs = Get-DbaAvailabilityGroup @agParams if (-not $allAGs) { Write-Warning "Keine Verfügbarkeitsgruppen auf $SqlInstance gefunden." return } # Zu entfernende Datenbanken ermitteln $targetDbs = @() if ($All) { Invoke-mssLogging -Message "Sammle alle Datenbanken, die in einer AG sind." -FunctionName $functionName -Level "INFO" foreach ($ag in $allAGs) { $agDbs = Get-DbaAgDatabase -SqlInstance $SqlInstance -SqlCredential $SqlCredential -AvailabilityGroup $ag.Name -ErrorAction SilentlyContinue $targetDbs += $agDbs | Select-Object -ExpandProperty Name } $targetDbs = $targetDbs | Select-Object -Unique } elseif ($Database) { $targetDbs = $Database } else { throw "Weder -All noch -Database angegeben." } if (-not $targetDbs) { Invoke-mssLogging -Message "Keine Datenbanken zum Entfernen gefunden." -FunctionName $functionName -Level "WARNING" return } # Für jede Datenbank die zugehörige AG finden und entfernen foreach ($dbName in $targetDbs) { # AG ermitteln, in der die DB Mitglied ist $agDb = Get-DbaAgDatabase -SqlInstance $SqlInstance -SqlCredential $SqlCredential -Database $dbName -ErrorAction SilentlyContinue if (-not $agDb) { $msg = "Datenbank '$dbName' ist in keiner Verfügbarkeitsgruppe (oder nicht vorhanden)." Invoke-mssLogging -Message $msg -FunctionName $functionName -Level "WARNING" $results += [PSCustomObject]@{ SqlInstance = $SqlInstance DatabaseName = $dbName Status = "NotInAG" Message = $msg } continue } $agName = $agDb.AvailabilityGroupName $secondaryInstances = $agDb | Get-DbaAgReplica -SqlInstance $SqlInstance -SqlCredential $SqlCredential | Where-Object { $_.Role -ne 'Primary' } | Select-Object -ExpandProperty Name # Entfernen aus AG $removeAction = "Datenbank '$dbName' aus AG '$agName' entfernen" if ($PSCmdlet.ShouldProcess($dbName, $removeAction)) { try { Invoke-mssLogging -Message $removeAction -FunctionName $functionName -Level "INFO" Remove-DbaAgDatabase -SqlInstance $SqlInstance -SqlCredential $SqlCredential -AvailabilityGroup $agName -Database $dbName -Confirm:$false -ErrorAction Stop $results += [PSCustomObject]@{ SqlInstance = $SqlInstance DatabaseName = $dbName Status = "RemovedFromAG" Message = "Erfolgreich aus AG '$agName' entfernt." } } catch { $errMsg = "Fehler beim Entfernen aus AG: $($_.Exception.Message)" Invoke-mssLogging -Message $errMsg -FunctionName $functionName -Level "ERROR" if ($EnableException) { throw } $results += [PSCustomObject]@{ SqlInstance = $SqlInstance DatabaseName = $dbName Status = "RemoveFromAGFailed" Message = $errMsg } continue } } else { $results += [PSCustomObject]@{ SqlInstance = $SqlInstance; DatabaseName = $dbName; Status = "RemoveSkipped"; Message = "WhatIf: Entfernen aus AG übersprungen." } continue } # Löschen auf sekundären Replikaten foreach ($secondary in $secondaryInstances) { $dropAction = "Datenbank '$dbName' auf sekundärem Knoten '$secondary' löschen" if ($PSCmdlet.ShouldProcess($dbName, $dropAction)) { try { Invoke-mssLogging -Message $dropAction -FunctionName $functionName -Level "INFO" Remove-DbaDatabase -SqlInstance $secondary -SqlCredential $SqlCredential -Database $dbName -Confirm:$false -ErrorAction Stop $results += [PSCustomObject]@{ SqlInstance = $secondary DatabaseName = $dbName Status = "DroppedOnSecondary" Message = "Datenbank auf '$secondary' gelöscht." } } catch { $errMsg = "Fehler beim Löschen auf '$secondary': $($_.Exception.Message)" Invoke-mssLogging -Message $errMsg -FunctionName $functionName -Level "ERROR" if ($EnableException) { throw } $results += [PSCustomObject]@{ SqlInstance = $secondary DatabaseName = $dbName Status = "DropOnSecondaryFailed" Message = $errMsg } } } else { $results += [PSCustomObject]@{ SqlInstance = $secondary; DatabaseName = $dbName; Status = "DropSkipped"; Message = "WhatIf: Löschen auf $secondary übersprungen." } } } } } catch { $errMsg = "Allgemeiner Fehler: $($_.Exception.Message)" Invoke-mssLogging -Message $errMsg -FunctionName $functionName -Level "ERROR" if ($EnableException) { throw } $results += [PSCustomObject]@{ SqlInstance = $SqlInstance; DatabaseName = $null; Status = "GlobalError"; Message = $errMsg } } } end { Invoke-mssLogging -Message "$functionName abgeschlossen." -FunctionName $functionName -Level "INFO" return $results } } |