- PR -

TransactionScope.Disposeにおける例外について

1
投稿者投稿内容
ARM
会議室デビュー日: 2008/07/21
投稿数: 3
投稿日時: 2008-07-21 10:22
[環境]
Windows Server 2003 SP2
SQL Server 2005
Visual Studio 2005

VB2005で作成したバッチプログラムで、TransactionScopeを利用した
トランザクション処理を行うのですが、大量データ(約5万件以上?)の
Insert処理を行うとTransactionScope.Dispose(End Using)で
例外が発生し、トランザクションが中止されてしまいます。
同様の現象を経験された方や原因を御存知の方がおられましたら
アドバイスをお願いします。

[内容]
・Temp1は41項目のテーブルですが、項目数が異なる他テーブルへの
 追加処理でもデータ量が多いと例外が発生します。
・40000件程度の追加処理だと正常終了してDBにデータが追加されますが、
 50000件以上になると例外が発生します。ただし、50000件の追加でも
 稀に正常終了することがあり、例外が発生する件数は多少変動します。
 (50000件程度が境界線だと思われます。)
・taTemp1.InsertQueryは、クエリの追加(クエリの構成ウィザード)で
 SQL文を指定して作成したメソッドです。


[スタックトレース]
---------------------------------------
トランザクションが中止されました。
場所 System.Transactions.TransactionStateAborted.BeginCommit(InternalTransaction tx, Boolean asyncCommit, AsyncCallback asyncCallback, Object asyncState)
場所 System.Transactions.CommittableTransaction.Commit()
場所 System.Transactions.TransactionScope.InternalDispose()
場所 System.Transactions.TransactionScope.Dispose()
---------------------------------------

[ソース]
---------------------------------------
Try

Using scope As New Transactions.TransactionScope(Transactions.TransactionScopeOption.Required), _
taTemp1 As New Temp1TableAdapters.Temp1TableAdapter

Dim cnt As Integer
For cnt = 1 To 50000
taTemp1.InsertQuery(
cnt.ToString, _
"val1", _
"val2", _
(〜省略〜)
"val40")
Next

scope.Complete()

End Using '←例外発生

Catch ex As Exception
'ログ出力
End Try
---------------------------------------
※最終的に実施したいのは、他のテーブルからSELECTした
 レコード件数分ループし、その中でデータを編集しつつ、
 Insert処理をすることですが、上記のテスト用の単純な
 INSERT処理ですら例外となっています。

さかもと
ぬし
会議室デビュー日: 2004/05/14
投稿数: 586
投稿日時: 2008-07-21 11:22
さかもとと申します。

transactionscopeは

scope.Complete()

と命令を発行したタイミングでコミットされるように思われますが、実際にはUsingを抜けるタイミングで確定されます。(Dispose時点でコミットされる)

Complete()は呼び出しをしたか/しないか のフラグでしかありません。

恐らくDisposeで失敗しているということではなく、このトランザクションの処理自体が失敗しているのではないでしょうか?

一定の件数以上で落ちるということであれば、タイムアウトで落ちているような気がしますが、そのような可能性は考えられないでしょうか?


_________________
------------------------------------------
拝啓、さかもとと申します♪
ARM
会議室デビュー日: 2008/07/21
投稿数: 3
投稿日時: 2008-07-21 12:46
さかもと様

ご回答ありがとうございます。
仰るとおり、確かにDispose時のDBコミット処理自体に問題があって
例外が発生しているように見えます。

タイムアウトについは、InsertQuery()などのクエリ実行部分で
SqlExceptionとして発生することは経験したことがありますが、
(「タイムアウトに達しました。操作が完了する前に〜」など)
Dispose(コミット)時点で発生することは想像してませんでした。
どこかに、トランザクション処理やコミット処理のタイムアウト値を
保持しているということでしょうか?

処理時間を見ると、ループ処理は1分ほどかかっていますが、
その後のDispose(コミット)が実行された瞬間(1秒以内)に
例外が発生しています。

さかもと
ぬし
会議室デビュー日: 2004/05/14
投稿数: 586
投稿日時: 2008-07-22 11:01
さかもとです。

自動トランザクションではなく、マニュアルトランザクションで試しても同じように例外で落ちますか?


_________________
------------------------------------------
拝啓、さかもとと申します♪
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2008-07-22 11:05
1分で発生しているなら高い確率でトランザクションのタイムアウトでしょう。
※デフォルトで1分です。

TransactionScopeのコンストラクタでタイムアウトを指定するか、構成ファイルでデフォルトのタイムアウトを伸ばすかしてみてください。

ただし、最大で10分までになります。
※これはMachine.configの設定で延ばすことはできますが止めたほうがいいでしょう。
ARM
会議室デビュー日: 2008/07/21
投稿数: 3
投稿日時: 2008-07-22 20:13
さかもと様、なちゃ様

返信が遅くなりまして申し訳ありません。
お二人が仰ったとおり、本現象はTransactionScopeの
タイムアウトによるものでした。
(「タイムアウト」というメッセージは出ないのですね。)

なちゃ様にアドバイス頂いた方法で、TransactionScopeの
タイムアウト値を変更した結果、正常終了しました。

大変助かりました。ありがとうございます。
1

スキルアップ/キャリアアップ(JOB@IT)