externalLibs/SQLPSX/SQLMaint/SQLMaint.psm1
function Invoke-DBMaint { <# .SYNOPSIS Implements full database maintenance. .DESCRIPTION Implements full database maintenance. .INPUTS Pipe ServerName .OUTPUTS None .EXAMPLE Invoke-DBMaint -server R2D2 -Databases "ALL" -Action "BKP_DB" -BackupOn c:\Temp -ReportOn c:\Temp Invoke-DBMaint -server R2D2 -Databases "SYSTEM" -Action "BKP_DB" -BackupOn c:\Temp -ReportOn c:\Temp Invoke-DBMaint -server R2D2 -Databases "USER" -Action "BKP_DB" -BackupOn c:\Temp -ReportOn c:\Temp Invoke-DBMaint -server R2D2 -Databases "USER" -Action "BKP_LOG" -BackupOn c:\Temp -ReportOn c:\Temp Invoke-DBMaint -server R2D2 -Databases "USER" -Action "IDX_ALL" -ReportOn c:\Temp Invoke-DBMaint -server R2D2 -Databases "USER" -Action "IDX_REBUILD" -ReportOn c:\Temp Invoke-DBMaint -server R2D2 -Databases "USER" -Action "IDX_REORG" -ReportOn c:\Temp Invoke-DBMaint -server R2D2 -Databases "USER" -Action "STATS_FULL" -ReportOn c:\Temp Invoke-DBMaint -server R2D2 -Databases "USER" -Action "STATS_SAMPLE" -ReportOn c:\Temp Invoke-DBMaint -server R2D2 -Databases "USER" -Action "CHECK_DB" -ReportOn c:\Temp Invoke-DBMaint -server R2D2 -Databases "DELHIST" -Action "DEL_HIST" -ReportOn c:\Temp -RemoveDataBackupsMSDB 10 -RemoveOldBackups 10 get-content c:\temp\servers.txt | Invoke-DBMaint -Databases "USER" -Action "CHECK_DB" -ReportOn c:\Temp .LINK http://sqlpsx.codeplex.com/ #> param ( [Parameter(Position=0, Mandatory=$true, ValueFromPipeline = $true)] [Microsoft.SqlServer.Management.Smo.Server] $Server, [Parameter(position=1,Mandatory = $true )] [ValidateSet("ALL", "USER", "SYSTEM","DELHIST")] [string] $Databases , [Parameter(position=2,Mandatory = $true )] [ValidateSet("BKP_DB","BKP_LOG","BKP_FILE","BKP_DIFF","IDX_ALL","IDX_REBUILD","IDX_REORG","STATS_SAMPLE","STATS_FULL","CHECK_DB","DEL_HIST")] [String] $Action , [Parameter(position=3,Mandatory = $false )] [string] $UserName = "" , [Parameter(position=4,Mandatory = $false )] [string] $Password = "" , [Parameter(position=5,Mandatory = $false )] [ValidateScript({Test-Path -path $_})] [String] $BackupOn = "c:\temp", [Parameter(position=6,Mandatory = $false )] [ValidateScript({Test-Path -path $_})] [String] $ReportOn = "", [Parameter(position=7,Mandatory = $false )] [ValidateRange(1,365)] [System.Int32] $RemoveOldBackups = 0, [Parameter(position=8,Mandatory = $false )] [ValidateRange(1,365)] [System.Int32] $RemoveOldBackupsReports = 0, [Parameter(position=9,Mandatory = $false )] [ValidateRange(1,365)] [System.Int32] $RemoveDataBackupsMSDB = 0 ) Begin { function Write-ScriptLog { param($msg,$date,$ReportOn) if ($ReportOn -ne "") { Add-Content -Path (Join-Path $ReportOn "Invoke_DBMaint_$($ServerName)_$($date).log") -Value $msg} Write-Output $msg } function Invoke-DBMaintBackup { param ($Action,$Databases,$ReportOn,$date,$dbs,$servername) [Microsoft.SqlServer.Management.Smo.BackupActionType] $actionbkp = "Database" $incremental = $false switch ($Action) { 'BKP_DB' {$extension = ".bak"} 'BKP_FILE' {$extension = ".bak"; $actionbkp = "File" } 'BKP_LOG' {$extension = ".trn"; $actionbkp = "Log" } 'BKP_DIFF' {$extension = "_Diff.bak" ; $incremental = $true } } Write-ScriptLog -msg $("Operation executed : BACKUP $($actionbkp) - Databases : $($databases) - Differential : $($incremental)") -date $($date) -reporton $($ReportOn) Write-ScriptLog -msg $("`n") -date $($date) -reporton $($ReportOn) $dbs | foreach { try { $InitialTime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" $DbName = $_.name if ($incremental) { Invoke-SqlBackup -sqlserver $_.parent -dbname $_.name -action $actionbkp -incremental -filepath (join-path $BackupOn "$($ServerName )$($_.name)$(get-date -format yyyyMMddhhmmss)$extension") -force } else { Invoke-SqlBackup -sqlserver $_.parent -dbname $_.name -action $actionbkp -filepath (join-path $BackupOn "$($ServerName )$($_.name)$(get-date -format yyyyMMddhhmmss)$extension") -force } $endtime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Write-ScriptLog -msg $("Initial Time : $($initialtime) End Time : $($endtime) .Backup $($actionbkp) for server $($ServerName) Database $($DbName) to $($BackupOn) completed.") -date $($date) -reporton $($ReportOn) } catch { Write-ScriptLog -msg $("$(get-date -format yyyy/MM/dd) : Backup $($actionbkp) FAILED for server $($ServerName) Database $($DbName). Error details $($error[0])") -date $($date) -reporton $($ReportOn) } } } function Invoke-DbMaintIndexes { param ($Action,$Databases,$ReportOn,$date,$dbs,$servername) Write-ScriptLog -msg $("Operation executed : Index $($action) - Databases : $($databases)") -date $($date) -reporton $($ReportOn) Write-ScriptLog -msg $("`n") -date $($date) -reporton $($ReportOn) $dbs | Get-SqlTable | Get-SqlIndex | foreach { $index = $_ Get-SqlIndexFragmentation $index | foreach { try { # If frag > 10 and < 30 and pages > 1000 , or choose reorg if (($_.AverageFragmentation -ge 10 -and $_.AverageFragmentation -le 30 -and $_.Pages -ge 1000) -or $action -eq "IDX_REORG") { $InitialTime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Invoke-SqlIndexDefrag $index $endtime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Write-ScriptLog -msg $("Initial Time : $($initialtime) End Time : $($endtime) .Server $($index.Server) Database $($index.$DbName) Table $($index.table) Index $($index.name) Avg Fragmentation $($_.AverageFragmentation) | Reorganize Completed." ) -date $($date) -reporton $($ReportOn) } # if frag > 30 and pages > 1000 or chosse rebuild elseif (($_.AverageFragmentation -gt 30 -and $_.Pages -ge 1000) -or $action -eq "IDX_REBUILD") { $InitialTime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Invoke-SqlIndexrebuild $index $endtime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Write-ScriptLog -msg $("Initial Time : $($initialtime) End Time : $($endtime) .Server $($ServerName) Database $($index.DbName) Table $($index.table) Index $($index.name) Avg Fragmentation $($_.AverageFragmentation)| Rebuild Completed.") -date $($date) -reporton $($ReportOn) } } catch { Write-ScriptLog $("$(get-date -format yyyy/MM/dd) : Index Action FAILED for server $($ServerName) Database $($index.DbName) Table $($index.table) Index $($index.name) . Error details $($error[0])") -date $($date) -reporton $($ReportOn) } } } } function invoke-dbmaintStats { param ($Action,$Databases,$ReportOn,$date,$dbs,$servername) Write-ScriptLog -msg $("Operation executed : Update Statistics $($action) - Databases : $($databases)") -date $($date) -reporton $($ReportOn) Write-ScriptLog -msg $("`n") -date $($date) -reporton $($ReportOn) $dbs | Get-SqlTable | Get-SqlStatistic | foreach { $table = $_ try { $InitialTime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" if ($Action -eq "STATS_FULL") { Update-SqlStatistic -statistic $_ -scanType "FullSCAN" } Else { Update-SqlStatistic -statistic $_ } $endtime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Write-ScriptLog -msg $("Initial Time : $($initialtime) End Time : $($endtime) .Server $($ServerName) Database $($Table.DbName) Table $($Table.table) | Statistics Updated.") -date $($date) -reporton $($ReportOn) } catch { Write-ScriptLog -msg $("$(get-date -format yyyy/MM/dd) : Statistics Update FAILED for server $($ServerName) Database $($Table.DbName) Table $($Table.table) . Error details $($error[0])") -date $($date) -reporton $($ReportOn) } } } function invoke-dbmaintcheckdb { param ($Action,$Databases,$ReportOn,$date,$dbs,$servername) Write-ScriptLog $("Operation executed : DBCC CHECKDB - Databases : $($databases)") -date $($date) -reporton $($ReportOn) Write-ScriptLog -msg $("`n") -date $($date) -reporton $($ReportOn) $dbs | foreach { $Database = $_ try { $InitialTime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Invoke-SqlDatabaseCheck $Database $endtime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Write-ScriptLog $("Initial Time : $($initialtime) End Time : $($endtime) .Server $($ServerName) Database $($Database.Name) | CHECKDB Completed." ) -date $($date) -reporton $($ReportOn) } catch { Write-ScriptLog $("$(get-date -format yyyy/MM/dd) : CHECKDB FAILED for server $($ServerName) Database $($Database.Name) . Error details $($error[0])") -date $($date) -reporton $($ReportOn) } } } function invoke-dbmaintHKMSDB { param ($RemoveDataBackupsMSDB,$ReportOn,$server,$servername) Write-ScriptLog $("Operation executed : Housekeeping MSDB Days $($RemoveDataBackupsMSDB)") -date $($date) -reporton $($ReportOn) Write-ScriptLog -msg $("`n") -date $($date) -reporton $($ReportOn) $Dtfinal = (Get-Date) - (New-TimeSpan -Days $RemoveDataBackupsMSDB) try { $InitialTime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" $Server.DeleteBackupHistory($Dtfinal) $endtime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Write-ScriptLog $("Initial Time : $($initialtime) End Time : $($endtime) .Server $($ServerName) | Housekeeping MSDB Completed." ) -date $($date) -reporton $($ReportOn) } catch { Write-ScriptLog -msg $($Error[0]) -date $($date) -reporton $($ReportOn) } } function invoke-dbmaintremoveoldbackups { param ($RemoveOldBackups,$date,$BackupOn,$ReportOn,$servername) Write-ScriptLog $("Operation executed : Removing Old Backups Days $($RemoveOldBackups)") -date $($date) -reporton $($ReportOn) Write-ScriptLog -msg $("`n") -date $($date) -reporton $($ReportOn) try { #Only strings match $servername AND not match .log $InitialTime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Get-ChildItem $($BackupOn) | Where-Object {$_.name -match "(.*$servername.*)[^\.log]" -and (get-date).subtract($_.LastWriteTime).days -ge $RemoveOldBackups } | remove-item -Force $endtime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Write-ScriptLog $("Initial Time : $($initialtime) End Time : $($endtime) .Server $($ServerName) | Removing Old Backups Completed." ) -date $($date) -reporton $($ReportOn) }catch { Write-ScriptLog $("$(get-date -format yyyy/MM/dd) : Remove Old Backups FAILED for server $($ServerName) . Error details $($error[0])") -date $($date) -reporton $($ReportOn) } } function invoke-dbmaintremoveoldbackupsreports { param ($RemoveOldBackupsReports,$date,$ReportOn,$servername) Write-ScriptLog $("Operation executed : Removing Old Reports Days $($RemoveOldBackupsReports)") -date $($date) -reporton $($ReportOn) Write-ScriptLog -msg $("`n") -date $($date) -reporton $($ReportOn) try { $InitialTime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" #Only strings match $servername AND match .log Get-ChildItem $($ReportOn) | Where-Object { $_.name -match "(.*$servername.*)(\.log)" -and (get-date).subtract($_.LastWriteTime).days -ge $RemoveOldBackupsReports } | remove-item -force $endtime = Get-Date -Format "yyyy/MM/dd hh:mm:ss" Write-ScriptLog $("Initial Time : $($initialtime) End Time : $($endtime) .Server $($ServerName) | Removing Old Eeports Completed." ) -date $($date) -reporton $($ReportOn) }catch { Write-ScriptLog $("$(get-date -format yyyy/MM/dd) : Remove Old Backups Reports FAILED for server $($ServerName) . Error details $($error[0])") -date $($date) -reporton $($ReportOn) } } } process { #Set Action Preference $ErrorActionPreference = "Continue" $date = get-date -format yyyyMMddhhmmss if ($Databases -eq "DELHIST" -or $Action -eq "DEL_HIST") {$Action = "DEL_HIST";$Databases = "DELHIST"} try { $ServerName = ((( $server -replace '\\','_') -replace '\[','') -replace '\]','') #Clean error $Error.Clear() #Try connect to the server if ($UserName -eq "" -and $Password -eq "") {$server = Get-SqlServer -sqlserver $server} else {$server = Get-SqlServer -sqlserver $server -username $UserName -password $Password} #Verify wich databases will be used switch ($Databases) { 'All' { $dbs = Get-SqlDatabase $server -force | Where-Object {$_.name -notmatch "tempdb"}} 'System' { $dbs = Get-SqlDatabase $server -force | where {$_.IsSystemObject -and $_.name -notmatch "tempdb"} } 'User' { $dbs = Get-SqlDatabase $server | Where-Object {$_.name -notmatch "tempdb"} } } # Only Backups if ($Action -match "^BKP_DB$|^BKP_LOG$|^BKP_FILE$|^BKP_DIFF$") { invoke-dbmaintbackup $Action $Databases $ReportOn $date $dbs $servername } #Reindex or Rebuild. Use fragmentation >= 10 and <=30 Reorg and update stats. > 30 Rebuild. Only indexes with pagecount > 1000 if ($Action -match "^IDX_ALL$|^IDX_REBUILD$|^IDX_REORG$") { invoke-dbmaintindexes $Action $Databases $ReportOn $date $dbs $servername } #Stats Sample or Full if ($Action -match "^STATS_SAMPLE|^STATS_FULL$") { invoke-dbmaintStats $Action $Databases $ReportOn $date $dbs $servername } #CheckDB if ($Action -eq "CHECK_DB") { invoke-dbmaintcheckdb $Action $Databases $ReportOn $date $dbs $servername } #Housekeeping MSDB if (($Action -eq "DEL_HIST" -and $RemoveDataBackupsMSDB -gt 0) -or $RemoveDataBackupsMSDB -gt 0 ) { invoke-dbmaintHKMSDB $RemoveDataBackupsMSDB $ReportOn $server $servername } if ($RemoveOldBackups -gt 0) { invoke-dbmaintremoveoldbackups $RemoveOldBackups $date $BackupOn $ReportOn $servername } if ($RemoveOldBackupsReports -gt 0 -and $ReportOn -ne "" ) { invoke-dbmaintremoveoldbackupsreports $RemoveOldBackupsReports $date $ReportOn $servername } } catch { Write-ScriptLog $("$(get-date -format yyyy/MM/dd) :Invoke-DBMaint FAILED for server $($ServerName) . Error details $($error[0])") -date $($date) -reporton $($ReportOn) } } } |