2010-05-06 4 views
3

Я успешно использую Powershell с SMO для резервного копирования большинства баз данных. Однако у меня есть несколько больших баз данных, в которых я получаю ошибку «timeout» «System.Data.SqlClient.SqlException: Timeout expired». Временной интервал последовательно происходит через 10 минут. Я попытался установить ConnectionContext.StatementTimeout на 0, 6000 и [System.Int32] :: MaxValue. Настройка не имела никакого значения. Я нашел несколько ссылок Google, которые указывают, что установка его на 0 делает ее неограниченной. Независимо от того, что я пытаюсь, тайм-ауты последовательно происходят через 10 минут. Я даже установил Тайм-аут удаленного запроса на сервере на 0 (через Studio Manager) безрезультатно. Ниже мое SMO-соединение, где я устанавливаю тайм-аут и фактическую функцию резервного копирования. Ниже приведен результат моего сценария.Параметр SMO ConnectionContext.StatementTimeout игнорируется

UPDATE Интересно, что я написал функцию резервного копирования в C# с помощью VS 2008 и тайм-аут переопределение делает работу в этой среде. Я в процессе включения этого процесса C# в свой сценарий Powershell, пока не узнаю, почему переопределение тайм-аута не работает с Powershell. Это очень раздражает!

function New-SMOconnection { 
    Param ($server, 
     $ApplicationName= "PowerShell SMO", 
     [int]$StatementTimeout = 0 
    ) 
# Write-Debug "Function: New-SMOconnection $server $connectionname $commandtimeout" 
    if (test-path variable:\conn) { 
     $conn.connectioncontext.disconnect() 
    } else { 
     $conn = New-Object('Microsoft.SqlServer.Management.Smo.Server') $server 
    } 
    $conn.connectioncontext.applicationName = $applicationName 
    $conn.ConnectionContext.StatementTimeout = $StatementTimeout 
    $conn.connectioncontext.Connect() 
    $conn 
} 

$smo = New-SMOConnection -server $server 
if ($smo.connectioncontext.isopen -eq $false) { 
    Throw "Could not connect to server $($server)." 
} 

Function Backup-Database { 
Param([string]$dbname) 
$db = $smo.Databases.get_Item($dbname) 
if (!$db) {"Database $dbname was not found"; Return} 
$sqldir = $smo.Settings.BackupDirectory + "\$($smo.name -replace ("\\", "$"))" 
$s = ($server.Split('\'))[0] 
$basedir = "\\$s\" + $($sqldir -replace (":", "$")) 

$dt = get-date -format yyyyMMdd-HHmmss   
$dbbk = new-object ('Microsoft.SqlServer.Management.Smo.Backup')   
$dbbk.Action = 'Database'   
$dbbk.BackupSetDescription = "Full backup of " + $dbname   
$dbbk.BackupSetName = $dbname + " Backup"   
$dbbk.Database = $dbname   
$dbbk.MediaDescription = "Disk" 
$target = "$basedir\$dbname\FULL" 
if (-not(Test-Path $target)) { New-Item $target -ItemType directory | Out-Null} 
$device = "$sqldir\$dbname\FULL\" + $($server -replace("\\", "$")) + "_" + $dbname + "_FULL_" + $dt + ".bak" 
$dbbk.Devices.AddDevice($device, 'File') 
$dbbk.Initialize = $True 
$dbbk.Incremental = $false 
$dbbk.LogTruncation = [Microsoft.SqlServer.Management.Smo.BackupTruncateLogType]::Truncate 
If (!$copyonly) { 
    If ($kill) {$smo.KillAllProcesses($dbname)} 
    $dbbk.SqlBackupAsync($server) 
} 
$dbbk 

}


Started SQL backups for server LCFSQLxxx\SQLxxx at 05/06/2010 15:33:16 
Statement TimeOut value set to 0. 

DatabaseName : OperationsManagerDW 
StartBackupTime : 5/6/2010 3:33:16 PM 
EndBackupTime : 5/6/2010 3:43:17 PM 
StartCopyTime : 1/1/0001 12:00:00 AM 
EndCopyTime  : 1/1/0001 12:00:00 AM 
CopiedFiles  : 
Status   : Failed 
ErrorMessage : System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. 
        The backup or restore was aborted. 
        10 percent processed. 
        20 percent processed. 
        30 percent processed. 
        40 percent processed. 
        50 percent processed. 
        60 percent processed. 
        70 percent processed. 
        at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) 
        at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 
        at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) 
        at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 
        at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async) 
        at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) 
        at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() 
        at Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery(String sqlCommand, ExecutionTypes executionType) 

Ended backups at 05/06/2010 15:43:23 

ответ

5

"Хлопающий мою голову несколько раз и говорил« о чем я думал?".

Я создал новое соединение и использовал его для подключения к серверу. Однако фактический оператор резервного копирования использует $ server (имя сервера) вместо объекта сервера smo с установленным соединением. Следовательно, оператор резервного копирования фактически устанавливает совершенно новое соединение, лишенное атрибута соединения, для сброса таймаута запроса по умолчанию.

Изменение оператора резервного копирования

$dbbk.SqlBackupAsync($smo) 

исправляет проблему.

+1

Я использую SqlBackup вместо SqlBakcupAsync, но этот совет по-прежнему работал на меня. Я передавал имя сервера, чтобы создать новое соединение. После переключения на передачу объекта сервера с ConnectionContext.StatementTimeout, установленным на [Int32] :: MaxValue, я смог взять резервную копию без выключения команды. –

0

Если вы используете SqlBackAsync, как вы узнаете, когда закончите резервное копирование? У меня такая же проблема, как и у вашего исходного кода ... но у моего кода есть функция, которая зависит от того, какая резервная копия завершилась успешно. Итак, если я вызываю async, мне нужна операция для опроса и проверка завершения резервного копирования.

Смежные вопросы