Microsoft.SqlServer.Management.Smo.Server.SqlRestore 超时问题
Microsoft.SqlServer.Management.Smo.Server.SqlRestore timeout issues
我有一个脚本,我根据找到的脚本创建了一个 powershell 脚本,Start-Migration。这是一个很棒的剧本,给了我很多非常好的想法;但是,在尝试恢复大型数据库或需要超过 10 分钟的数据库时,我 运行 遇到了一些问题。我试图同时使用我发现的 invoke-sqlcmd2 函数和 class 来恢复 microsoft.sqlserver.management.smo 命名空间。两者都在 10 分钟后超时。我还尝试增加连接超时甚至将连接设置为 1200。欢迎提出任何建议。
Function Restore-SQLDatabase {
<#
.SYNOPSIS
Restores .bak file to SQL database. Creates db if it doesn't exist. $filestructure is
a custom object that contains logical and physical file locations.
.EXAMPLE
$filestructure = Get-SQLFileStructures $sourceserver $destserver $ReuseFolderstructure
Restore-SQLDatabase $destserver $dbname $backupfile $filestructure
.OUTPUTS
$true if success
$true if failure
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[object]$server,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$dbname,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$backupfile,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[object]$filestructure
)
$servername = $server.Name
$server.ConnectionContext.StatementTimeout = 0
$restore = New-Object "Microsoft.SqlServer.Management.Smo.Restore"
foreach ($file in $filestructure.databases[$dbname].destination.values) {
$movefile = New-Object "Microsoft.SqlServer.Management.Smo.RelocateFile"
$movefile.LogicalFileName = $file.logical
$movefile.PhysicalFileName = $file.physical
$null = $restore.RelocateFiles.Add($movefile)
}
Write-Host "Restoring $dbname to $servername" -ForegroundColor Yellow
try{
$Percent = [Microsoft.SqlServer.Management.Smo.PercentCompleteEventHandler]{
Write-Progress -Id 1 -Activity "Restoring $dbname to $ServerName" -PercentComplete $_.Percent -Status ([System.String]::Format("Progress: {0}%",$_.Percent))
}
$restore.add_PercentComplete($Percent)
$restore.PercentCompleteNotification = 1
$restore.add_Complete($Complete)
$restore.ReplaceDatabase = $true
$restore.Database = $dbname
$restore.Action = "Database"
$restore.NoRecovery = $false
$device = New-Object -TypeName Microsoft.SqlServer.Management.Smo.BackupDeviceItem
$device.Name = $backupfile
$device.DeviceType = "File"
$restore.Devices.Add($device)
Write-Progress -Id 1 -Activity "Restoring $dbname to $servername" -PercentComplete 0 -Status([System.String]::Format("Progress: {0}%",0))
$restore.SqlRestore($servername)
# $query = $restore.Script($ServerName)
# Write-Host $query
# Invoke-Sqlcmd2 -ServerInstance $servername -Database master -Query $query -ConnectionTimeout 1200
# Write-Host "Restoring $dbname to $servername from " $restore.Devices.ToString() -ForegroundColor Magenta
Write-Progress -Id 1 -Activity "Restore $dbname to $servername" -Status "Complete" -Completed
return $true
}
catch{
Write-Error $_.Exception.ToString()
Write-Warning "Restore failed: $($_.Exception.InnerException.Message)"
return $false
}
当恢复过程发生时,$restore.SqlRestore($ServerName),在我的大型数据库上它 returns 说脚本超时。我想弄清楚如何纠正这个问题。我试过增加 statementtimeout = 1200 并且它在 10 分钟后仍然停止。我什至尝试向我们调用 invoke-sqlcmd 如您所见,我在尝试不同的选项时将其注释掉了。我现在束手无策。
如果你必须使用你找到的脚本
我认为“$server.ConnectionContext.StatementTimeout = 0”这行实际上没有做任何事情或改变超时阈值。
尝试将此行改为此行
$server = New-Object("Microsoft.SqlServer.Management.Smo.Server") $server
$server.ConnectionContext.StatementTimeout = 0
$server.ConnectionContext.Connect()
但是,我建议完全避免这种方法,因为您可以使用更简单的 SQLPS Cmdlet。您使用的方法来自很久以前,当时我们没有实际的 PowerShell cmdlet 可用于 SQL。
现在,我们有 Restore-SQLDatabase cmdlet,它让您只需一行即可完成代码现在约 30 行的工作!
如何使用还原-SQL数据库代替
这样简单多了,我想你会非常感谢我的。
Restore-SqlDatabase -ServerInstance "$server\InstanceName" `
-Database $dbname `-BackupFile $BackupFile
然后...就是这样。一条线!与以前不同,您还可以在此处轻松指定超时。指定最大超时:
Restore-SqlDatabase -ServerInstance "$server\InstanceName" `
-Database $dbname -BackupFile $BackupFile -ConnectionTimeout 0
这应该可以帮助您入门。相信我,使用 Cmdlet 比使用您在网上找到的一些随机脚本要容易得多。
好的,我让它工作了。我不完全确定它为什么起作用,但这就是我所做的。我创建了一个参数 $Server 如下:
$Server = New-Object Microsoft.SqlServer.Management.Smo.Server $Source
$Server.ConnectionContext.ConnectTimeout = 0
现在,当我调用实际执行恢复的函数时,我正在做一些我不需要做的事情:
$ServerName = $server.Name
我没有使用 $ServerName,而是使用了对象 $server:
$restore.SqlRestore($servername) # Original Script
$restore.SqlRestore($server) # Change
现在它保持打开状态的时间足以完成恢复过程。
我有一个脚本,我根据找到的脚本创建了一个 powershell 脚本,Start-Migration。这是一个很棒的剧本,给了我很多非常好的想法;但是,在尝试恢复大型数据库或需要超过 10 分钟的数据库时,我 运行 遇到了一些问题。我试图同时使用我发现的 invoke-sqlcmd2 函数和 class 来恢复 microsoft.sqlserver.management.smo 命名空间。两者都在 10 分钟后超时。我还尝试增加连接超时甚至将连接设置为 1200。欢迎提出任何建议。
Function Restore-SQLDatabase {
<#
.SYNOPSIS
Restores .bak file to SQL database. Creates db if it doesn't exist. $filestructure is
a custom object that contains logical and physical file locations.
.EXAMPLE
$filestructure = Get-SQLFileStructures $sourceserver $destserver $ReuseFolderstructure
Restore-SQLDatabase $destserver $dbname $backupfile $filestructure
.OUTPUTS
$true if success
$true if failure
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[object]$server,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$dbname,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$backupfile,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[object]$filestructure
)
$servername = $server.Name
$server.ConnectionContext.StatementTimeout = 0
$restore = New-Object "Microsoft.SqlServer.Management.Smo.Restore"
foreach ($file in $filestructure.databases[$dbname].destination.values) {
$movefile = New-Object "Microsoft.SqlServer.Management.Smo.RelocateFile"
$movefile.LogicalFileName = $file.logical
$movefile.PhysicalFileName = $file.physical
$null = $restore.RelocateFiles.Add($movefile)
}
Write-Host "Restoring $dbname to $servername" -ForegroundColor Yellow
try{
$Percent = [Microsoft.SqlServer.Management.Smo.PercentCompleteEventHandler]{
Write-Progress -Id 1 -Activity "Restoring $dbname to $ServerName" -PercentComplete $_.Percent -Status ([System.String]::Format("Progress: {0}%",$_.Percent))
}
$restore.add_PercentComplete($Percent)
$restore.PercentCompleteNotification = 1
$restore.add_Complete($Complete)
$restore.ReplaceDatabase = $true
$restore.Database = $dbname
$restore.Action = "Database"
$restore.NoRecovery = $false
$device = New-Object -TypeName Microsoft.SqlServer.Management.Smo.BackupDeviceItem
$device.Name = $backupfile
$device.DeviceType = "File"
$restore.Devices.Add($device)
Write-Progress -Id 1 -Activity "Restoring $dbname to $servername" -PercentComplete 0 -Status([System.String]::Format("Progress: {0}%",0))
$restore.SqlRestore($servername)
# $query = $restore.Script($ServerName)
# Write-Host $query
# Invoke-Sqlcmd2 -ServerInstance $servername -Database master -Query $query -ConnectionTimeout 1200
# Write-Host "Restoring $dbname to $servername from " $restore.Devices.ToString() -ForegroundColor Magenta
Write-Progress -Id 1 -Activity "Restore $dbname to $servername" -Status "Complete" -Completed
return $true
}
catch{
Write-Error $_.Exception.ToString()
Write-Warning "Restore failed: $($_.Exception.InnerException.Message)"
return $false
}
当恢复过程发生时,$restore.SqlRestore($ServerName),在我的大型数据库上它 returns 说脚本超时。我想弄清楚如何纠正这个问题。我试过增加 statementtimeout = 1200 并且它在 10 分钟后仍然停止。我什至尝试向我们调用 invoke-sqlcmd 如您所见,我在尝试不同的选项时将其注释掉了。我现在束手无策。
如果你必须使用你找到的脚本
我认为“$server.ConnectionContext.StatementTimeout = 0”这行实际上没有做任何事情或改变超时阈值。
尝试将此行改为此行
$server = New-Object("Microsoft.SqlServer.Management.Smo.Server") $server
$server.ConnectionContext.StatementTimeout = 0
$server.ConnectionContext.Connect()
但是,我建议完全避免这种方法,因为您可以使用更简单的 SQLPS Cmdlet。您使用的方法来自很久以前,当时我们没有实际的 PowerShell cmdlet 可用于 SQL。
现在,我们有 Restore-SQLDatabase cmdlet,它让您只需一行即可完成代码现在约 30 行的工作!
如何使用还原-SQL数据库代替
这样简单多了,我想你会非常感谢我的。
Restore-SqlDatabase -ServerInstance "$server\InstanceName" `
-Database $dbname `-BackupFile $BackupFile
然后...就是这样。一条线!与以前不同,您还可以在此处轻松指定超时。指定最大超时:
Restore-SqlDatabase -ServerInstance "$server\InstanceName" `
-Database $dbname -BackupFile $BackupFile -ConnectionTimeout 0
这应该可以帮助您入门。相信我,使用 Cmdlet 比使用您在网上找到的一些随机脚本要容易得多。
好的,我让它工作了。我不完全确定它为什么起作用,但这就是我所做的。我创建了一个参数 $Server 如下:
$Server = New-Object Microsoft.SqlServer.Management.Smo.Server $Source
$Server.ConnectionContext.ConnectTimeout = 0
现在,当我调用实际执行恢复的函数时,我正在做一些我不需要做的事情:
$ServerName = $server.Name
我没有使用 $ServerName,而是使用了对象 $server:
$restore.SqlRestore($servername) # Original Script
$restore.SqlRestore($server) # Change
现在它保持打开状态的时间足以完成恢复过程。