2011-01-07 3 views
3

Я пытаюсь восстановить базу данных из файла резервной копии с помощью SMO. Если база данных еще не существует, она работает нормально. Однако, если база данных уже существует, я не получаю ошибок, но база данных не перезаписывается.Восстановление SMO базы данных SQL не перезаписывается

Процесс «восстановления» по-прежнему занимает столько же времени, поэтому он выглядит так, как будто он работает и выполняет восстановление, но в итоге база данных не изменилась.

Я делаю это в Powershell, используя SMO. Код немного длинный, но я включил его ниже. Вы заметите, что я установил $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." 
} 
+0

Я не знаком с SMO, но я нашел это (http://www.sqldbatips.com/showarticle.asp?ID=40) пример кода для выполнения восстановлений. Возможно, сравните свой код с этим. Я заметил, что вы говорите «правда», а не «правда» ... не уверен, что это проблема. – IamIC

+1

$ true - правильное представление PowerShell логического значения true. –

ответ

4

У меня такая же проблема, я пытаюсь восстановить базу данных со спины, взятой с того же сервера, но с другим именем. Я профилировал процесс восстановления, и он не добавляет «с движением» с разными именами файлов. Вот почему он будет восстанавливать базу данных, когда база данных не существует, но сбой при ее выполнении. Возникла проблема с свойством .PhysicalFileName.

0

Так же, как если вы делаете это от T-SQL, если есть что-то с помощью базы данных, то, что будет блокировать восстановление. Всякий раз, когда мне поручено восстановить базу данных, мне нравится сначала отключить ее (с немедленным откатом). Это убивает любые соединения с db. Возможно, вам придется сначала установить его в Интернете; Я не помню, если восстановление достаточно умное, чтобы понять, что файлы, которые вы переписываете, относятся к восстановленной базе данных или нет. Надеюсь это поможет.

+0

Спасибо за предложение. Я думал о том, что он используется, и sp_who2 нигде не раскрывал никого в БД. Сервер используется только несколькими разработчиками, которые сидят в одной комнате со мной, поэтому я смог это исключить. Я добавил код, чтобы взять DB в автономном режиме на всякий случай. –

3

Я делал восстановление SMO и сталкивался с ошибками. Единственный способ, которым я нашел диагностировать проблему, - запустить SQL-профиль во время выполнения моего сценария powershell.

Это показало мне фактический 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" 
Смежные вопросы