Параметр SMO ConnectionContext.StatementTimeout игнорируется

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

ОБНОВЛЕНИЕ Интересно, что я написал функцию резервного копирования на C#, используя VS 2008, и переопределение времени ожидания работает в этой среде. Я нахожусь в процессе включения этого процесса С# в свой сценарий 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

person Woody    schedule 06.05.2010    source источник


Ответы (2)


«Неоднократно бить меня по голове и говорить: «О чем я думал?»».

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

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

$dbbk.SqlBackupAsync($smo)

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

person Woody    schedule 17.06.2010
comment
Я использую SqlBackup вместо SqlBakcupAsync, но этот совет все еще работает для меня. Я передавал имя сервера, поэтому создавалось новое соединение. После переключения на передачу объекта сервера с ConnectionContext.StatementTimeout, для которого установлено значение [Int32]::MaxValue, я смог сделать резервную копию без истечения времени ожидания команды. - person Orlando Colamatteo; 21.12.2012

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

person Knows Not Much    schedule 19.06.2012