web-dev-qa-db-ja.com

sqlbulkcopyのuseinternaltransactionプロパティの目的は何ですか?

PowerShellScriptをテストして、SQLServerとOracleデータベース間で複数のテーブルの一括コピーを実行しています。宛先がOracleの場合、実行することで進行状況を監視できます。

Mytableからcount(*)を選択

個々にコミットされた単一のバッチサイズのチャンク。

SQL-Serverの宛先を使用すると、単一のトランザクションがあるようです。これは、最初の試行でネットワークエラーが原因でロールバックされました。 2番目はまだ進行中です。内部トランザクションを使用すると、個々のチャンクがコミットされますか?

バルクコピーの使用は、少しばかりまたはまったくないように思われます。失敗した場合は、最初からやり直すことができます。

$source = 'ora'
$dest = 'sql'

$SourceConnectionString_sql      = "Data Source=localhost;Initial Catalog=MySQLDatabase;Integrated Security=True"
$SourceConnectionString_ora      = "Data Source=MyOracleDatabase;User ID=MyUser;Password=MyPassword"

$DestinationConnectionString_sql = "Data Source=localhost;Initial Catalog=MySqleDatabase2;Integrated Security=True"
$DestinationConnectionString_ora = "Data Source=MyOracleDatabase2;User ID=MyUser;Password=MyPassword"


# -----------------------------------------------------------------------------

$SQL_Select_TABLES = "SELECT name FROM sys.Tables ORDER BY 1"
$SQL_Select_TABLES = "SELECT Top 1 name FROM sys.Tables"

$ORA_Select_TABLES = "SELECT TABLE_NAME Name FROM user_tables ORDER BY 1"
$ORA_Select_TABLES = "SELECT TABLE_NAME Name FROM user_tables where ROWNUM = 1"

$notifyAfter = 1000
# -----------------------------------------------------------------------------
if ($ora_dll -eq $null)
{
    $ora_dll = [System.Reflection.Assembly]::LoadWithPartialName("Oracle.DataAccess") 
}

$global:start = get-date
$notifyFunction={ 
    $dauer = [int]((get-date) - $global:start).TotalMilliseconds / 1000
    Write-Host "$tableName $($args[1].RowsCopied) $dauer"
    } 

if ($dest -eq 'sql')
{
    $bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $DestinationConnectionString_sql
}
else
{
    $bulkCopy = new-object ("Oracle.DataAccess.Client.OracleBulkCopy") $DestinationConnectionString_ora
}


$bulkCopy.BatchSize = 50000
$bulkCopy.BulkCopyTimeout=10000000
if ($notifyAfter -gt 0){
    $bulkCopy.NotifyAfter=$notifyafter
    if ($dest -eq 'sql')
    {
       $bulkCopy.Add_SQlRowscopied($notifyFunction)
    }
    else
    {
       $bulkCopy.Add_OracleRowscopied($notifyFunction)
    }

}

if ($source -eq 'sql')
{
    $sourceConnection  = New-Object System.Data.SqlClient.SQLConnection($SourceConnectionString_sql)
    $sourceConnection.open()

    $commandSourceData  = New-Object system.Data.SqlClient.SqlCommand($SQL_Select_TABLES, $sourceConnection)
    $da = New-Object system.Data.SqlClient.SqlDataAdapter($commandSourceData)
    $dt = New-Object system.Data.datatable
    [void]$da.fill($dt)
}
else
{
    $sourceConnection  = New-Object Oracle.DataAccess.Client.OracleConnection($SourceConnectionString_ora)
    $sourceConnection.open()

    $commandSourceData  = New-Object Oracle.DataAccess.Client.OracleCommand($Ora_Select_TABLES, $sourceConnection)
    $da = New-Object Oracle.DataAccess.Client.OracleDataAdapter($commandSourceData)
    $dt = New-Object system.Data.datatable
    [void]$da.fill($dt)
}

foreach ($table in $dt)
{
    $tablename  = $table.name
    $Tablename
    try
    {
        $sql = "SELECT * FROM $tableName"
        if ($source -eq 'sql')
        {
            $commandSourceData  = New-Object system.Data.SqlClient.SqlCommand($sql,$sourceConnection)
        }
        else
        {
            $commandSourceData  = New-Object Oracle.DataAccess.Client.oracleCommand($sql,$sourceConnection)
        }
        $reader = $commandSourceData.ExecuteReader()
        $bulkCopy.DestinationTableName = $tableName
        $bulkCopy.WriteToServer($reader)
    }
    catch
    {
        $ex = $_.Exception
        Write-Host "Write-DataTable$($connectionName):$ex.Message"
    }
    finally
    {
        $reader.close()
    }
}
$sourceConnection.close()
$bulkCopy.close()

((get-date) - $start).TotalSeconds
2
bernd_k

私があなたを正しく理解している場合:

  • BatchSize を使用して、負荷をチャンクに分割します(例:10k行)
  • seInternalTransaction 各バッチがトランザクションであるかどうかを判別します

そう:

  • BatchSize = 0-> UseInternalTransactionは無関係です
  • BatchSize> 0-> ApplyUseInternalTransactionが指定されています

参考までに、SQLServerの負荷を非ブロッキング方式で監視します

select count(*) from Mytable WITH (nolock)
3
gbn