我想将SQL DB备份带到共享路径并通过PS执行恢复。以下是执行操作的代码
function restore-TemporaryInLocal($dbName,$backupPath,$sqlServer,$isOverWrite,$DecDBObj,$sqlInstanceName)
{
$percentEventHandler = [Microsoft.SqlServer.Management.Smo.PercentCompleteEventHandler] { Write-Host "Restoration progress : " $_.Percent "%" }
$completedEventHandler = [Microsoft.SqlServer.Management.Common.ServerMessageEventHandler] { Write-Host $_.Error.Message}
# Get the default file and log locations
# (If DefaultFile and DefaultLog are empty, use the MasterDBPath and MasterDBLogPath values)
$DataFileLoc = $sqlServer.Settings.DefaultFile
$LogFileLoc = $sqlServer.Settings.DefaultLog
if ($DataFileLoc.Length -eq 0) {
$DataFileLoc = $sqlServer.Information.MasterDBPath
}
if ($LogFileLoc.Length -eq 0) {
$LogFileLoc = $sqlServer.Information.MasterDBLogPath
}
# Identify the backup file to use, and the name of the database copy to create
#$BackupFile= 'D:\SQLJobs\Errdb2.bak'
#$RestoredDBName = 'ErrDB2_20101016'
# Build the physical file names for the database copy
$DBFile = $DataFileLoc + $dbname + '_Data.mdf'
$LogFile = $LogFileLoc + $dbname + '_Log.ldf'
# Use the backup file name to create the backup device
$bdi = new-object ('Microsoft.SqlServer.Management.Smo.BackupDeviceItem') ($backupPath, 'File')
# Create the new restore object, set the database name and add the backup device
$restoreObj = new-object('Microsoft.SqlServer.Management.Smo.Restore')
$restoreObj.Database = $dbName
$restoreObj.Devices.Add($bdi)
# Get the file list info from the backup file
$FileList = $restoreObj.ReadFileList($sqlServer)
foreach ($file in $FileList) {
$rsfile = new-object('Microsoft.SqlServer.Management.Smo.RelocateFile')
$rsfile.LogicalFileName = $file.LogicalName
if ($file.Type -eq 'D'){
$rsfile.PhysicalFileName = $DBFile
}
else {
$rsfile.PhysicalFileName = $LogFile
}
$restoreObj.RelocateFiles.Add($rsfile)
}
# Restore the database
$restoreObj.ReplaceDatabase=$isOverWrite;
#Write-Host "Replace DB :"$restoreObj.ReplaceDatabase
$restoreObj.add_PercentComplete($percentEventHandler)
$restoreObj.add_Complete($completedEventHandler)
if($isOverWrite -eq $true)
{
Write-Host "Taking DB Offline";
$script="ALTER DATABASE $dbname SET OFFLINE WITH ROLLBACK IMMEDIATE";
#Write-Host $script $dbname $sqlInstanceName
Invoke-SQLcmd -Server $sqlInstanceName -Database $dbName $script
Write-Host "Getting DB Online";
$DecDBObj.SetOnline();
}
Write-Host "Initiating DB restore..."
$restoreObj.SqlRestore($sqlServer)
}
function take-BackupToLocal($backupDirectory,$serverName,$backupDB,$isCopyOnly,$serverRef)
{
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum") | Out-Null
$percentEventHandler = [Microsoft.SqlServer.Management.Smo.PercentCompleteEventHandler] { Write-Host "Database backed up" $_.Percent "%" }
$completedEventHandler = [Microsoft.SqlServer.Management.Common.ServerMessageEventHandler] { Write-Host $_.Error.Message
Write-Host "Backup Path:"$targetPath
}
$dbList = $serverRef.Databases
$BackupDB =$BackupDB.Trim();
$DBexists=$false;
if(test-path $backupDirectory)
{
$timestamp = Get-Date -format yyyy-MM-dd-HHmmss
$targetPath = $backupDirectory + "\" + $backupDB + "_" + $timestamp + ".bak"
foreach ($database in $dbList | where { $_.IsSystemObject -eq $False })
{
$dbName = $database.Name
if($database.Name -eq $BackupDB -and $database.Status -ieq "normal"){
$DBexists=$true;
$smoBackup = New-Object ("Microsoft.SqlServer.Management.Smo.Backup")
$smoBackup.Action = "Database"
$smoBackup.BackupSetDescription = "Full Backup of " + $dbName
$smoBackup.BackupSetName = $dbName + " Backup"
$smoBackup.Database = $dbName
$smoBackup.MediaDescription = "Disk"
$smoBackup.CopyOnly=$isCopyOnly
$smoBackup.Devices.AddDevice($targetPath, "File")
$smoBackup.PercentCompleteNotification=5
$smoBackup.add_PercentComplete($percentEventHandler)
$smoBackup.add_Complete($completedEventHandler)
$smoBackup.SqlBackup($serverRef)
return $targetPath;
}else{
Write-Host "Cannot perform a backup as the DB is in:" $database.Status " mode";
}
}
if($DBexists -eq $false)
{
Write-Host "$BackupDB DB not found in $serverName.Please check the DB & Server details"
}
}
else
{
Write-Host "Cannot find the path specified. Contact admin"
Write-Host "backup path:"$backupDirectory
}
}
$sqlName= "*************"
$serverName="******";
# Set new or existing databse name to restote backup
$backupDB= "AdventureWorksDW2012"
# Set the existing backup file path
#$backupPath= "D:\Automation\Ps-scripts\Backups\tempdb1_2017-05-25-222232.bak"
#Load the required assemlies SMO and SmoExtended.
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null
$percentEventHandler = [Microsoft.SqlServer.Management.Smo.PercentCompleteEventHandler] { Write-Host "Restoration progress : " $_.Percent "%" }
$completedEventHandler = [Microsoft.SqlServer.Management.Common.ServerMessageEventHandler] { Write-Host $_.Error.Message}
try{
# Connect SQL Server.
$sqlServer = New-Object ('Microsoft.SqlServer.Management.Smo.Server') $sqlName
$ExistingDB=$sqlServer.Databases.Item($backupDB)
$backupDirectory="\\***********\ps_jobs_backup_shared";
$isCopyOnly=$true;
if($ExistingDB.EncryptionEnabled -eq $true)
{
$needToDecrypt = Read-Host -Prompt 'Specify if backup needs to be decrypted (Y/N)'
}
if($needToDecrypt -ieq "y")
{
#Write-Host "decryption code...."
$decServerSqlName="***************"
Write-Host "Initiating Backup..."
$DecryptDB="tempDB1"
$decSqlServer = New-Object ('Microsoft.SqlServer.Management.Smo.Server') $decServerSqlName
$decServerSqlName="****************"
$isOverWrite=$true;
$DecDBObj=$decSqlServer.Databases.Item($DecryptDB)
$backupPath=take-BackupToLocal -backupDirectory $backupDirectory -serverName $sqlName -backupDB $backupDB -isCopyOnly $isCopyOnly -serverRef $sqlServer
restore-TemporaryInLocal -dbName $DecryptDB -backupPath $backupPath -sqlServer $decSqlServer -isOverWrite $isOverWrite -DecDBObj $DecDBObj -sqlInstanceName $decServerSqlName
}elseif($needToDecrypt -ieq "n")
{
Write-Host "Initiating a encrypted backup...";
take-BackupToLocal -backupDirectory $backupDirectory -serverName $sqlName -backupDB $backupDB -isCopyOnly $isCopyOnly -serverRef $sqlServer
}
}
catch
{
$_.Exception.GetBaseException().Message
}
现在上面的代码工作正常。但是,当我再次执行相同的代码时,TEST-PATH条件失败[解决方法:每次运行后需要再次重新打开PS IDE]
以下是前两次运行的日志。
Specify if backup needs to be decrypted (Y/N): y
Initiating Backup...
Database backed up 5 %
Database backed up 10 %
Database backed up 100 %
BACKUP DATABASE successfully processed 25625 pages in 8.435 seconds (23.733 MB/sec).
Taking DB Offline
Getting DB Online
Initiating DB restore...
Restoration progress : 10 %
Restoration progress : 20 %
Restoration progress : 100 %
RESTORE DATABASE successfully processed 25625 pages in 7.429 seconds (26.946 MB/sec).
第二轮:
Specify if backup needs to be decrypted (Y/N): y
Initiating Backup...
Cannot find the path specified. Contact admin
backup path: \\sanky555\ps_jobs_backup_shared