web-dev-qa-db-ja.com

TransactionScope TransactionAbortedException-トランザクションはロールバックされません。すべきですか?

(SQL SERVER 2008)TransactionScope(.Complete())内でトランザクションタイムアウトエラーが発生した場合、トランザクションがロールバックされると思いますか?

更新:
エラーは、実際には.Complete()ではなく、閉じ中括弧(つまり、.Dispose())でスローされています。完全なエラーは次のとおりです。

The transaction has aborted. System.Transactions.TransactionAbortedException TransactionAbortedException System.Transactions.TransactionAbortedException: The transaction has aborted. ---> System.TimeoutException: Transaction Timeout
   --- End of inner exception stack trace ---
   at System.Transactions.TransactionStateAborted.BeginCommit(InternalTransaction tx, Boolean asyncCommit, AsyncCallback asyncCallback, Object asyncState)
   at System.Transactions.CommittableTransaction.Commit()
   at System.Transactions.TransactionScope.InternalDispose()
   at System.Transactions.TransactionScope.Dispose()

私が知る限り、トランザクションはロールバックされず、SPID/session_idに対してKILLを発行するまでテーブルはロックされたままでした。

DBCC OPENTRANを使用して最も古いトランザクションを取得し、それを強制終了しました。 KILL WITH STATUSを試しましたが、何もロールバックされていないため、ステータスが利用できないというメッセージが表示されます。 sys.dm_exec_sessionsのSPID/session_idのステータスは「スリープ中」です。コードスニペット:

try
{            
    using (var transaction = new TransactionScope())
    {
        LOTS OF WORK CARRIED OUT WITH LINQ ENTITIES/SubmitChanges() etc.
        transaction.Complete();  //Transaction timeout
    }
    return result;
}
catch (Exception ex)
{
    logger.ErrorException(ex.Message, ex);
    result.Fail(ex.Message);
    return result;
}

更新:
問題は完全には解決されていませんが、他の誰かがこの問題を抱えている場合は、さらに詳しい情報があります。

  1. LINQ to SQLを使用しており、トランザクションスコープ内でcontext.SubmitChanges()を呼び出します。私はたくさんの挿入を行っています。 SQL Serverプロファイラーは、挿入ごとに個別のINSERTステートメントが発行されることを示します。
  2. 開発中、SubmitChanges()を呼び出す前にスレッドを60秒間スリープすると(デフォルトのTransactionScopeタイムアウトは60秒)、TransactionScope.Complete()を呼び出すと別のエラーが発生します(操作はトランザクションの状態に対して無効です。 )。
  3. .SubmitChages()の後、.Complete()の直前で60秒間スリープすると、「トランザクションが中止されました-System.TimeoutException:TransactionTimeout」が表示されます。
  4. ただし、私の開発マシンでは、DBCC opentranを使用しているときに開いているトランザクションが見つからないことに注意してください。これは、トランザクションがロールバックすると予想されるためです。
  5. 次に、この質問の下部にあるコードを構成ファイルに追加すると(Webサイトにここに挿入できませんでした)、TransactionScopeのタイムアウトが2分に増加します(調査によると、これが機能しない場合は動作する場合は、machine.configに、これよりも低い設定が優先されている可能性があります)。
  6. これによりトランザクションの中止は停止しますが、更新の性質上、コアビジネステーブルのロックは最大2分になる可能性があるため、デフォルトのSqlCommandタイムアウトである30秒を使用する他のselectコマンドはタイムアウトします。理想的ではありませんが、そこに座ってアプリケーションを完全に保持するオープントランザクションよりも優れています。
  7. 数日前に悲惨なリリースがあり、アップグレードの途中でディスクスペースが不足したため(!)、データベースの縮小機能を使用することになりました。これは、使用後にパフォーマンスの問題を引き起こす可能性があります。
  8. データベースの再構築と、いくつかのビジネス機能の再考が行われていると感じています...

18
MT.

TransactionAbortedExceptionは実際にはタイムアウトだと思います。その場合、TransactionAbortedExceptionのInnerExceptionがタイムアウトであることがわかります。

トランザクションスコープのタイムアウトがコマンドのタイムアウトよりも長いことを確認することで、それを取り除くことができるはずです。

トランザクションスコープを次のように変更してみてください。

new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(60))

また、コンテキストに明示的なタイムアウトを設定します。次のようになります。

myContext.CommandTimeout = 30; //This is seconds
16
alun

物理ファイルmachine.configを変更してこの問題を解決します。

1。ファイルをローカライズする必要があります:

  • 2ビット: C:\ Windows\Microsoft.NET\Framework\v4.0.30319\Config\machie.config
  • 64ビット: C:\ Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config

2。次のコードを追加する必要があります。

<system.transactions>
     <defaultSettings timeout="00:59:00" />
</system.transactions>
0