3

Powershell と SMO を使用して、ほとんどのデータベースを正常にバックアップしています。ただし、「タイムアウト」エラー「System.Data.SqlClient.SqlException: タイムアウト期限切れ」を受け取る大規模なデータベースがいくつかあります。タイムアウトは常に 10 分で発生します。ConnectionContext.StatementTimeout を 0、6000、および [System.Int32]::MaxValue に設定しようとしました。設定に違いはありませんでした。0 に設定すると無制限になることを示す多くの Google リファレンスを見つけました。何を試しても、タイムアウトは一貫して 10 分で発生します。サーバーの Remote Query Timeout を (Studio Manager 経由で) 0 に設定しても無駄です。以下は、タイムアウトと実際のバックアップ機能を設定した SMO 接続です。さらに下は、私のスクリプトからの出力です。

更新 興味深いことに、私は VS 2008 を使用して C# でバックアップ関数を作成しましたが、タイムアウトのオーバーライドはその環境内で機能します。Powershell だけではタイムアウトのオーバーライドが機能しない理由がわかるまで、その C# プロセスを 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
4

2 に答える 2

5

「何度も頭を叩いて、『何を考えていたの?』と言いました」.

新しい接続を作成し、それを使用してサーバーに接続しました。ただし、実際のバックアップ ステートメントでは、接続が確立された $smo サーバー オブジェクトではなく、$server (サーバー名) が使用されます。したがって、backup ステートメントは実際には、デフォルトのステートメント タイムアウトをリセットするために接続属性を持たないまったく新しい接続を確立します。

バックアップステートメントの変更

$dbbk.SqlBackupAsync($smo)

問題を修正します。

于 2010-06-17T21:14:48.100 に答える
0

SqlBackAsync を使用している場合、バックアップがいつ完了したかをどのように知ることができますか? 元のコードと同じ問題があります...しかし、私のコードには、バックアップが正常に完了することに依存する機能があります。したがって、async を呼び出す場合は、ポーリングしてバックアップが完了するかどうかを確認する操作が必要です。

于 2012-06-19T09:58:08.627 に答える