2

例) デッドロックが発生した場合、以下の SQL コマンドは、ロールバック後の SQL トランザクションを割り当てた場合でも、正常に実行されます。SQL Server で作成された新しい暗黙のトランザクションが原因のようです。

コマンドがゾンビ トランザクションで実行されているという例外を ADO.NET がスローすると予想する人もいるでしょう。ただし、そのような例外はスローされません。(これは ASP.NET のバグだと思います。) さらに、ゾンビ トランザクションが原因で、ファイナルDispose()は黙ってロールバックを無視します。

暗黙のトランザクションで誰もコマンドを実行できないようにするにはどうすればよいですか? または、トランザクションがゾンビであることを確認する方法は? 私はそれを見つけてゾンビトランザクションCommit()Rollback()チェックしましたが、テストのためにそれらを呼び出すことができます:)

また、IsolationLevel を読み取るとチェックが行われることもわかりましたが、単純な呼び出しtransaction.IsolationLevel.ToString();が将来のオプティマイザーによって削除されないかどうかはわかりません。または、ゲッターを呼び出す他の安全な方法を知っていますか (リフレクションや IL の放出を使用せずに)。

編集: Remus Rusanu は、このような状況は通常発生しないと指摘しました。はい、本当です。通常、コードにバグがある場合に発生します。私たちの場合、データベースに失敗を保存しようとしていた最終ステートメントに、いくつかのロギング ルーチンがありました。現在、将来このようなバグを検出する方法を見つけようとしています。これらのバグはテストが難しいためです。提供されたトランザクションがゾンビであることを ADO.NET がチェックする場合、このバグははるかに簡単に発見されます。私は2つの可能性を見つけました:

  1. 暗黙的なトランザクションの作成をオフにします - これが可能かどうかはわかりません。
  2. コマンドを実行する前に、ゾンビ トランザクションが実行されるかどうかを確認してください。
4

3 に答える 3

2

あなたが説明するものは存在しません。トランザクションのロールバックは、アプリケーションで非常に目に見える例外をスローします。なんらかの理由で、あなたのコードが例外を捕捉し、黙ってそれを無視し、トランザクションがロールバックされた後もステートメントを実行し続けていると私は信じています。

于 2010-06-07T16:07:10.283 に答える
0

バグが原因だったので、おそらくあなたの問題とは直接関係ありませんが、それでも興味深いかもしれません。すべてのエラーが原因でトランザクションがロールバックされるわけではないため、トランザクションが「部分的に成功」する場合があります。一部のステートメントはエラーになり、他のステートメントは正常に完了します。エラー時にサーバーがトランザクションを中止する
オプションSET XACT_ABORT ONがあります。

あなたの質問を考慮すると、暗黙的なトランザクションをオフにすることはできません (SQL ステートメントを実行すると、別のトランザクションが既にアクティブでない限り、暗黙的なトランザクションが作成されます)。したがって、必要なときにトランザクションが存在することを確認するために、エラーを正しく処理する必要があります。TransactionScopeクラスを
見てください。これを使用して、コードでこれらのトランザクションを管理することを回避できます。

于 2010-06-20T17:34:59.043 に答える
0

//あなたの説明に基づいて、あなたのコードが効果的にこれを行うと推測しています

        SqlConnection conn = new SqlConnection("ConnectionString");
        SqlCommand cmd = new SqlCommand("insert into ....");

        cmd.Connection = conn;

        conn.Open();

        SqlTransaction tran = conn.BeginTransaction();


        cmd.Transaction = tran;

        tran.Rollback(); //or tran.Dispose();

        cmd.ExecuteNonQuery();

これにより、cmd がトランザクションの範囲外で実行されます。

行 cmd.Connection = conn; を削除します。あなたが探していると私が思う動作を実現します(たとえば、トランザクションが有効でなくなったため、コマンドは失敗します。)

SqlConnection conn = new SqlConnection("ConnectionString");
    SqlCommand cmd = new SqlCommand("insert into ....");

    //cmd.Connection = conn;

    conn.Open();

    SqlTransaction tran = conn.BeginTransaction();
    cmd.Connection = tran.Connection;

    cmd.Transaction = tran;

    tran.Rollback(); //or tran.Dispose();

    cmd.ExecuteNonQuery();
于 2010-06-21T19:18:53.093 に答える