Sql server 2008 SQL数据库的SMO恢复不';不覆盖
我正在尝试使用SMO从备份文件还原数据库。如果数据库不存在,那么它可以正常工作。但是,如果数据库已经存在,则不会出现错误,但不会覆盖数据库 “恢复”过程仍然需要同样长的时间,因此看起来它正在工作并进行恢复,但最终数据库没有改变 我使用SMO在Powershell中执行此操作。代码有点长,但我已经在下面包含了它。您会注意到我确实设置了Sql server 2008 SQL数据库的SMO恢复不';不覆盖,sql-server-2008,powershell,smo,database-restore,Sql Server 2008,Powershell,Smo,Database Restore,我正在尝试使用SMO从备份文件还原数据库。如果数据库不存在,那么它可以正常工作。但是,如果数据库已经存在,则不会出现错误,但不会覆盖数据库 “恢复”过程仍然需要同样长的时间,因此看起来它正在工作并进行恢复,但最终数据库没有改变 我使用SMO在Powershell中执行此操作。代码有点长,但我已经在下面包含了它。您会注意到我确实设置了$restore.ReplaceDatabase=$true。此外,我使用try-catch块并报告任何错误(我希望如此),但没有返回任何错误 有明显的错误吗?有没有
$restore.ReplaceDatabase=$true
。此外,我使用try-catch块并报告任何错误(我希望如此),但没有返回任何错误
有明显的错误吗?有没有可能我没有报告一些错误,并且对我隐瞒了
感谢您提供的任何帮助或建议
function Invoke-SqlRestore {
param(
[string]$backup_file_name,
[string]$server_name,
[string]$database_name,
[switch]$norecovery=$false
)
# Get a new connection to the server
[Microsoft.SqlServer.Management.Smo.Server]$server = New-SMOconnection -server_name $server_name
Write-Host "Starting restore to $database_name on $server_name."
Try {
$backup_device = New-Object("Microsoft.SqlServer.Management.Smo.BackupDeviceItem") ($backup_file_name, "File")
# Get local paths to the Database and Log file locations
If ($server.Settings.DefaultFile.Length -eq 0) {$database_path = $server.Information.MasterDBPath }
Else { $database_path = $server.Settings.DefaultFile}
If ($server.Settings.DefaultLog.Length -eq 0 ) {$database_log_path = $server.Information.MasterDBLogPath }
Else { $database_log_path = $server.Settings.DefaultLog}
# Load up the Restore object settings
$restore = New-Object Microsoft.SqlServer.Management.Smo.Restore
$restore.Action = 'Database'
$restore.Database = $database_name
$restore.ReplaceDatabase = $true
if ($norecovery.IsPresent) { $restore.NoRecovery = $true }
Else { $restore.Norecovery = $false }
$restore.Devices.Add($backup_device)
# Get information from the backup file
$restore_details = $restore.ReadBackupHeader($server)
$data_files = $restore.ReadFileList($server)
# Restore all backup files
ForEach ($data_row in $data_files) {
$logical_name = $data_row.LogicalName
$physical_name = Get-FileName -path $data_row.PhysicalName
$restore_data = New-Object("Microsoft.SqlServer.Management.Smo.RelocateFile")
$restore_data.LogicalFileName = $logical_name
if ($data_row.Type -eq "D") {
# Restore Data file
$restore_data.PhysicalFileName = $database_path + "\" + $physical_name
}
Else {
# Restore Log file
$restore_data.PhysicalFileName = $database_log_path + "\" + $physical_name
}
[Void]$restore.RelocateFiles.Add($restore_data)
}
$restore.SqlRestore($server)
# If there are two files, assume the next is a Log
if ($restore_details.Rows.Count -gt 1) {
$restore.Action = [Microsoft.SqlServer.Management.Smo.RestoreActionType]::Log
$restore.FileNumber = 2
$restore.SqlRestore($server)
}
}
Catch {
$ex = $_.Exception
Write-Output $ex.message
$ex = $ex.InnerException
while ($ex.InnerException) {
Write-Output $ex.InnerException.message
$ex = $ex.InnerException
}
Throw $ex
}
Finally {
$server.ConnectionContext.Disconnect()
}
Write-Host "Restore ended without any errors."
}
就像从T-SQL执行此操作一样,如果有什么东西在使用数据库,则会阻止恢复。每当我负责恢复数据库时,我喜欢先将其脱机(立即回滚)。这将终止与数据库的任何连接。您可能需要先将其设置回在线状态;我不记得恢复是否足够聪明,能够意识到您正在覆盖的文件是否属于您正在恢复的数据库。希望这能有所帮助。我遇到了同样的问题,我正在尝试从同一台服务器恢复数据库,但名称不同。 我已经分析了恢复过程,它没有添加具有不同文件名的“with move”。这就是为什么它会在数据库不存在时恢复数据库,但在数据库存在时会失败。
.PhysicalFileName属性有问题。我在执行SMO还原时遇到错误。我发现诊断问题的唯一方法是在执行powershell脚本期间运行SQL配置文件 这显示了正在执行的实际T-SQL。然后我将其复制到一个查询中并尝试执行它。这向我展示了实际的错误:在我的例子中,我的数据库有多个需要重新定位的数据文件 附加的脚本适用于只有一个数据文件的数据库
Param
(
[Parameter(Mandatory=$True)][string]$sqlServerName,
[Parameter(Mandatory=$True)][string]$backupFile,
[Parameter(Mandatory=$True)][string]$newDBName
)
# Load assemblies
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-Null
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum") | Out-Null
# Create sql server object
$server = New-Object ("Microsoft.SqlServer.Management.Smo.Server") $sqlServerName
# Copy database locally if backup file is on a network share
Write-Host "Loaded assemblies"
$backupDirectory = $server.Settings.BackupDirectory
Write-Host "Backup Directory:" $backupDirectory
$fullBackupFile = $backupDirectory + "\" + $backupFile
Write-Host "Copy DB from: " $fullBackupFile
# Create restore object and specify its settings
$smoRestore = new-object("Microsoft.SqlServer.Management.Smo.Restore")
$smoRestore.Database = $newDBName
$smoRestore.NoRecovery = $false;
$smoRestore.ReplaceDatabase = $true;
$smoRestore.Action = "Database"
Write-Host "New Database name:" $newDBName
# Create location to restore from
$backupDevice = New-Object("Microsoft.SqlServer.Management.Smo.BackupDeviceItem") ($fullBackupFile, "File")
$smoRestore.Devices.Add($backupDevice)
# Give empty string a nice name
$empty = ""
# Specify new data file (mdf)
$smoRestoreDataFile = New-Object("Microsoft.SqlServer.Management.Smo.RelocateFile")
$defaultData = $server.DefaultFile
if (($defaultData -eq $null) -or ($defaultData -eq $empty))
{
$defaultData = $server.MasterDBPath
}
Write-Host "defaultData:" $defaultData
$smoRestoreDataFile.PhysicalFileName = Join-Path -Path $defaultData -ChildPath ($newDBName + "_Data.mdf")
Write-Host "smoRestoreDataFile.PhysicalFileName:" $smoRestoreDataFile.PhysicalFileName
# Specify new log file (ldf)
$smoRestoreLogFile = New-Object("Microsoft.SqlServer.Management.Smo.RelocateFile")
$defaultLog = $server.DefaultLog
if (($defaultLog -eq $null) -or ($defaultLog -eq $empty))
{
$defaultLog = $server.MasterDBLogPath
}
$smoRestoreLogFile.PhysicalFileName = Join-Path -Path $defaultLog -ChildPath ($newDBName + "_Log.ldf")
Write-Host "smoRestoreLogFile:" $smoRestoreLogFile.PhysicalFileName
# Get the file list from backup file
$dbFileList = $smoRestore.ReadFileList($server)
# The logical file names should be the logical filename stored in the backup media
$smoRestoreDataFile.LogicalFileName = $dbFileList.Select("Type = 'D'")[0].LogicalName
$smoRestoreLogFile.LogicalFileName = $dbFileList.Select("Type = 'L'")[0].LogicalName
# Add the new data and log files to relocate to
$smoRestore.RelocateFiles.Add($smoRestoreDataFile)
$smoRestore.RelocateFiles.Add($smoRestoreLogFile)
# Restore the database
$smoRestore.SqlRestore($server)
"Database restore completed successfully"
我不熟悉SMO,但我发现了这个()示例代码用于执行恢复。也许可以将您的代码与此进行比较。我注意到你说的是“$true”而不是“true”。。。不确定这是否是问题所在。$true是布尔true的正确PowerShell表示形式。感谢您的建议。我曾想过它正在使用,而sp_who2在任何时候都没有透露数据库中的任何其他人。这个服务器只被和我坐在同一个房间里的几个开发人员使用,所以我可以排除这种可能性。我添加了使数据库离线的代码,以防万一。