From b5c20188275c993389f118fa91d29979959b1da9 Mon Sep 17 00:00:00 2001 From: Masayuki Ozawa Date: Thu, 7 Jun 2018 21:50:13 +0900 Subject: [PATCH] =?UTF-8?q?Runspace=20=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=97?= =?UTF-8?q?=E3=81=9F=E3=82=AF=E3=82=A8=E3=83=AA=E5=AE=9F=E8=A1=8C=E7=94=A8?= =?UTF-8?q?=E3=82=B9=E3=82=AF=E3=83=AA=E3=83=97=E3=83=88=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Backup-Database.ps1" | 6 +- PowerShell/Start-ParallelQuery.ps1 | 155 ++++++++++++++++++ 2 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 PowerShell/Start-ParallelQuery.ps1 diff --git "a/Management Tools/\343\203\207\343\203\274\343\202\277\343\203\231\343\203\274\343\202\271\343\203\220\343\203\203\343\202\257\343\202\242\343\203\203\343\203\227/Backup-Database.ps1" "b/Management Tools/\343\203\207\343\203\274\343\202\277\343\203\231\343\203\274\343\202\271\343\203\220\343\203\203\343\202\257\343\202\242\343\203\203\343\203\227/Backup-Database.ps1" index 83930ce..ee3d32b 100644 --- "a/Management Tools/\343\203\207\343\203\274\343\202\277\343\203\231\343\203\274\343\202\271\343\203\220\343\203\203\343\202\257\343\202\242\343\203\203\343\203\227/Backup-Database.ps1" +++ "b/Management Tools/\343\203\207\343\203\274\343\202\277\343\203\231\343\203\274\343\202\271\343\203\220\343\203\203\343\202\257\343\202\242\343\203\203\343\203\227/Backup-Database.ps1" @@ -164,12 +164,14 @@ try{ $cmd.Dispose() - $con.Close() - $con.Dispose() Write-Output ("Backup Success [{0}] " -f $dbname) }catch{ return $Error[0] }finally{ + if($con -ne $null){ + $con.Close() + $con.Dispose() + } $ErrorActionPreference = $orgErrorActionPreference } } diff --git a/PowerShell/Start-ParallelQuery.ps1 b/PowerShell/Start-ParallelQuery.ps1 new file mode 100644 index 0000000..3592649 --- /dev/null +++ b/PowerShell/Start-ParallelQuery.ps1 @@ -0,0 +1,155 @@ +[CmdletBinding()] +Param( + [int]$ConnectionTimeout = 15, + [Parameter(Mandatory=$True)] + [string]$ServerInstance, + [Parameter(Mandatory=$True)] + [string]$Username, + [Parameter(Mandatory=$True)] + [string]$Password, + [Parameter(Mandatory=$True)] + [pscustomobject[]]$SQL, + [switch]$UniqueAppName, + [switch]$DisableConnectionPool +) + + +##### Function definition #### +function Out-Message([string]$Msg, [switch]$Error, [switch]$Info ){ + Write-Host ("[{0}] $Msg" -f (Get-Date).ToString("yyyy/MM/dd HH:mm:ss.fff"), $Msg) -ForegroundColor $(if($Error){"Red"} elseif($Info){"Green"} else{"White"}) +} +############################ + +$ErrorActionPreference = "Stop" + +$success = 0 +$failed = 0 + +$RunspaceSize = $SQL.Count + +Out-Message -Msg ("=" * 50) +Out-Message "Script Settings:" +Out-Message ("Connection Timeout:[{0}] / Runspace Size:[{2}]" -f $ConnectionTimeout, $CommandTimeout, $RunspaceSize) +Out-Message -Msg ("=" * 50) + +$sw = [system.diagnostics.stopwatch]::startNew() + +$constring = New-Object System.Data.SqlClient.SqlConnectionStringBuilder +$constring["Data Source"] = $ServerInstance +$constring["User Id"] = $Username +$constring["Password"] = $Password +$constring["Connect Timeout"] = $ConnectionTimeout +if ($DisableConnectionPool){ + $constring["Pooling"] = $false +} + + + +try{ + $minpoolsize = $maxpoolsize = $RunspaceSize + $runspacePool = [runspacefactory]::CreateRunspacePool($minPoolSize, $maxPoolSize) + $runspacePool.Open() + + $Command = { + Param( + [System.Data.SqlClient.SqlConnectionStringBuilder]$constring, + [PSCustomObject]$sql + ) + try{ + $orgErrorActionPreference = $ErrorActionPreference + $ErrorActionPreference = "SilentlyContinue" + $constring["Initial Catalog"] = $sql.Database + $con = New-Object System.Data.SqlClient.SqlConnection + $con.ConnectionString = $constring + + $con.Open() + + if ($sql.IsDataSet -ne $True){ + $cmd = $con.CreateCommand() + $cmd.CommandTimeout = $sql.CommandTimeout + + $cmd.CommandText = $sql.Text + + [void]$cmd.ExecuteNonQuery() + + $cmd.Dispose() + }else{ + $da = New-Object System.Data.SqlClient.SqlDataAdapter -ArgumentList $sql.Text, $con + $ds = New-Object System.Data.DataSet + $da.Fill($ds) + $ds.Tables[0] | Out-GridView + $ds.Dispose() + $da.Dispose() + } + Write-Output ("Query Complete [{0}] " -f $sql.Text) + }catch{ + return $Error[0] + }finally{ + if($con -ne $null){ + $con.Close() + $con.Dispose() + } + + $ErrorActionPreference = $orgErrorActionPreference + } + } + $RunspaceCollection = New-Object System.Collections.ArrayList + $Result = New-Object System.Collections.ArrayList + + $cnt = 1 + foreach ($Source in $SQL){ + if ($UniqueAppName){ + $constring["Application Name"] = ([GUID]::NewGuid()).ToString() + } + + $powershell = [PowerShell]::Create().AddScript($Command).AddArgument($constring).AddArgument($Source) + $powershell.RunspacePool = $runspacePool + [void]$RunspaceCollection.Add([PSCustomObject] @{ + QueryNo = $cnt + Runspace = $powershell.BeginInvoke(); + PowerShell = $powershell + StartTime = Get-Date + SQL = $Source.text + }) + Out-Message -Msg ("Start [#{0}] : {1}" -f $cnt++, $Source.text) + } + + # 処理完了の待機 + while($RunspaceCollection){ + foreach($runspace in $RunspaceCollection){ + if ($runspace.Runspace.IsCompleted){ + $ret = $runspace.powershell.EndInvoke($runspace.Runspace) + $runspace.PowerShell.Dispose() + + if (($ret | Get-Member).TypeName[0] -eq [System.Management.Automation.ErrorRecord]){ + Out-Message -Msg ("Error [#{0}] : [Start Time : {1} / Execution Time : {2}]" -f $runspace.QueryNo, $runspace.StartTime, ((Get-Date) - $runspace.StartTime).TotalSeconds) -Error + Out-Message -Msg $ret.Exception.GetBaseException() -Error + $failed +=1 + }else{ + Out-Message -Msg ("Success [#{0}] : [Start Time : {1} / Execution Time : {2}]" -f $runspace.QueryNo, $runspace.StartTime, ((Get-Date) - $runspace.StartTime).TotalSeconds) -Info + $success +=1 + } + [void]$Result.Add($ret) + $RunspaceCollection.Remove($runspace) + break + } + } + Start-Sleep -Milliseconds 5 + } + +}catch{ + Write-Output $Error[0] +}finally{ + if ($runspacePool -ne $null){ + $runspacePool.Close() + $runspacePool.Dispose() + } +} + + +$sw.Stop() + +Out-Message -Msg ("=" * 50) +Out-Message -Msg ("Total execution time (sec) : [{0}]" -f $sw.Elapsed.TotalSeconds) +Out-Message -Msg ("[Result] Success : [{0}] / Failed : [{1}]" -f $success, $failed) +Out-Message -Msg ("=" * 50)