web-dev-qa-db-ja.com

SQLTransactionがエラーを完了しました

アプリケーションで次のエラーが発生しました。

このSQLTransactionは完了しました。使用できなくなりました

スタックトレースは以下に添付されています– Zombie CheckRollbackについて書かれています。

コードの間違いは何ですか?

注:このエラーは1回だけ発生しました。

[〜#〜]更新[〜#〜]

From MSDN --SqlTransaction.Rollback Method

接続が終了した場合、またはトランザクションがサーバー上ですでにロールバックされている場合、ロールバックはInvalidOperationExceptionを生成します。

From トランザクションのゾンビチェック-エラー

このエラーがさまざまなアプリケーションで表示されるのを私が見た最も頻繁な理由の1つは、アプリケーション間での共有SqlConnectionです。

[〜#〜]コード[〜#〜]

public int SaveUserLogOnInfo(int empID)
{
        int? sessionID = null;
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();
            SqlTransaction transaction = null;
            try
            {
                transaction = connection.BeginTransaction();
                sessionID = GetSessionIDForAssociate(connection, empID, transaction);

                    //Other Code

                //Commit
                transaction.Commit();
            }
            catch
            {
                //Rollback
                if (transaction != null)
                {
                    transaction.Rollback();
                    transaction.Dispose();
                    transaction = null;
                }

                //Throw exception
                throw;
            }
            finally
            {
                if (transaction != null)
                {
                    transaction.Dispose();
                }
            }
        }

        return Convert.ToInt32(sessionID,CultureInfo.InvariantCulture);

   }

スタックトレース

enter image description here


[〜#〜]参照[〜#〜]

  1. ゾンビトランザクションとは何ですか?
  2. トランザクションのゾンビチェック-エラー
  3. SqlTransactionが完了しました
  4. http://forums.asp.net/t/1579684.aspx/1
  5. "このSqlTransactionは完了しました。使用できなくなりました。" ...構成エラー?
  6. dotnet.sys-con.com --SqlClient接続プールが公開されました
  7. スレッドの中止によりゾンビトランザクションが残り、SqlConnectionが壊れます

13
LCJ

作業の一部をコンパイラに任せて、それをtry/catch/finallyでラップする必要があります。

また、Rollbackステージで問題が発生した場合、またはサーバーへの接続が切断された場合、Commitが例外をスローすることがあることを期待する必要があります。そのため、try/catchでラップする必要があります。

try
{
    transaction.Rollback();
}
catch (Exception ex2)
{
    // This catch block will handle any errors that may have occurred 
    // on the server that would cause the rollback to fail, such as 
    // a closed connection.
    Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
    Console.WriteLine("  Message: {0}", ex2.Message);
}

これは、 ロールバックメソッドのMSDNドキュメントページ から正確にコピーされます。

ゾンビ取引があるのではないかと心配しているようです。貼り付けた場合、問題ないようです。トランザクションが完了しました。これとは何の関係もありません。あなたがそれらを保持している場合はそれへの参照を削除し、それを忘れてください。


From MSDN --SqlTransaction.Rollback Method

接続が終了した場合、またはトランザクションがサーバー上ですでにロールバックされている場合、ロールバックはInvalidOperationExceptionを生成します。

新しい例外を再スローして、データが保存されていない可能性があることをユーザーに通知し、更新して確認するようにユーザーに依頼します

注:このエラーは1回だけ発生しました。

それなら多くを言うのは非常に難しいです。単に// Other Codeなどは単に時間がかかり、すべてが殺されました。接続が切断されたか、ブロックしていたために管理者が意図的に接続を切断した可能性があります。

コードの間違いは何ですか?

それを過度に複雑にします。それははるかに簡単にすることができます:

using (var connection = new SqlConnection(connectionString))
{
    connection.Open();
    using(var transaction = connection.BeginTransaction())
    {
        try
        {
            sessionID = GetSessionIDForAssociate(connection, empID, transaction);
            //Other Code
            transaction.Commit();
         }
         catch
         {
            transaction.Rollback();
            throw;
         }
    }
}

間違えるコードがはるかに少なくなります。

7
Marc Gravell

以下のコードを使用してこのエラーを再現できます。1000タスクを使用してSQLを実行し、約300タスクが正常に完了した後、_timeout error_に関する多くの例外がExecuteNonQuery()で発生し始めます。

次に、次のエラー_This SqlTransaction has completed_がtransaction.RollBack();で発生し、その呼び出しスタックにもZombieCheck()が含まれます。

(1000タスクの単一プログラムで十分なプレッシャーがない場合は、コンパイルされた複数のexeファイルを同時に実行することも、複数のコンピューターを使用して1つのデータベースに対して実行することもできます。)

したがって、このエラーの原因の1つは、接続で問題が発生している可能性があることを推測します。次に、トランザクションエラーも発生します。

_Task[] tasks = new Task[1000];
for (int i = 0; i < 1000; i++)
{
    int j = i;
    tasks[i] = new Task(() =>
         ExecuteSqlTransaction("YourConnectionString", j)
        );
}

foreach (Task task in tasks)
{
    task.Start();
}       

/////////////    

public void ExecuteSqlTransaction(string connectionString, int exeSqlCou)
{

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();

        SqlCommand command = connection.CreateCommand();
        SqlTransaction transaction;

        // Start a local transaction.
        transaction = connection.BeginTransaction();

        // Must assign both transaction object and connection
        // to Command object for a pending local transaction
        command.Connection = connection;
        command.Transaction = transaction;

        try
        {
            command.CommandText =
                "select * from Employee";
            command.ExecuteNonQuery();

            // Attempt to commit the transaction.
            transaction.Commit();

            Console.WriteLine("Execute Sql to database."
                + exeSqlCou);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Commit Exception Type: {0}", ex.GetType());
            Console.WriteLine("  Message: {0}", ex.Message);


            // Attempt to roll back the transaction.
            try
            {
                transaction.Rollback();
            }
            catch (Exception ex2)
            {
                // This catch block will handle any errors that may have occurred
                // on the server that would cause the rollback to fail, such as
                // a closed connection.
                Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
                Console.WriteLine("  Message: {0}", ex2.Message);

            }
        }
    }
}
_

さらに、2回連続してコミットすると、この例外も呼び出されます。

_       transaction.Commit();
       transaction.Commit();
_

または、コミット前に接続が閉じられた場合も、このエラーが発生します。

_       connection.Close();
       transaction.Commit();
_

更新:

別の新しいテーブルを作成し、それに50万個のデータを挿入するのは奇妙だと思います。

次に、_select * from newtable_ sqlで100000タスクを使用し、5つのプログラムを同時に実行します。今回はタイムアウトエラーが発生しますが、transaction.Rollback()の場合、_SQLTransaction has completed error_は呼び出されませんでした。

ただし、タイムアウトエラーが発生した場合は、catchブロックにジャンプし、catchブロックでtransaction.Commit()を再度実行すると、_SQLTransaction has completed error_が発生します。

2
yu yang Jian

私は一度このエラーを経験しましたが、行き詰まり、何が問題になっているのかわかりません。実際、私はレコードを削除していましたが、ストアドプロシージャではその子を削除していませんでした。特に、Stored ProcedureのdeleteステートメントはTransaction境界内にありました。そのトランザクションコードをストアドプロシージャから削除し、この“This SqlTransaction has completed; it is no longer usable.”のエラーの発生を取り除きました。

1
ARC

このメッセージは、トランザクションがすでに正常にコミットされているの後に例外をスローするコードを記述したためです。Commitメソッドまたは処理できます)の後に記述したコードを確認してください。 Try..Catchを使用し、最後にBlocks :)を使用します。

0
Ahmed Elbatt