什么是&QUOT的原因;而在另一个会话&QUOT使用事务上下文; [英] What is the reason of "Transaction context in use by another session"

查看:218
本文介绍了什么是&QUOT的原因;而在另一个会话&QUOT使用事务上下文;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在找这个错误的根源的描述:由另一个会话使用事务上下文

I'm looking for a description of the root of this error: "Transaction context in use by another session".

我把它有时在我的单元测试,所以我不能提供摄制code之一。但我不知道什么是设计错误的原因。

I get it sometimes in one of my unittests so I can't provider repro code. But I wonder what is "by design" reason for the error.

更新:从SQL Server 2008中,我得到的错误似乎是单线程的地方错误再次为SQLEXCEPTION。但可能我有单元测试的互动,因为我在那里得到一次(MSTest的在VS2008SP1)运行几个测试误差。 但失败的测试是这样的:

UPDATE: the error returns as SqlException from SQL Server 2008. A place where I get the error seems to be single-threaded. But probably I have unittests interaction as I get the error where run several tests at once (MSTest in VS2008sp1). But the failing test looks like:

  • 创建一个对象,并将其保存里面的DB-事务(提交)
  • 创建的TransactionScope
  • 在试图打开一个连接 - 在这里,我得到的SQLException这样的堆栈跟踪:

System.Data.SqlClient.SqlException: Transaction context in use by another session.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
   at System.Data.SqlClient.SqlInternalConnectionTds.PropagateTransactionCookie(Byte[] cookie)
   at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()

我发现这些职位:

I've found these posts:

  • <一个href="http://blogs.msdn.com/asiatech/archive/2009/08/10/system-transaction-may-fail-in-multiple-thread-environment.aspx" rel="nofollow">http://blogs.msdn.com/asiatech/archive/2009/08/10/system-transaction-may-fail-in-multiple-thread-environment.aspx
  • http://msdn.microsoft.com/en-us/library/ ff649002.aspx
  • http://blogs.msdn.com/asiatech/archive/2009/08/10/system-transaction-may-fail-in-multiple-thread-environment.aspx
  • http://msdn.microsoft.com/en-us/library/ff649002.aspx

但我不明白的共享同一个事务中的事务范围内的多个线程将导致以下异常:由另一个会话事务上下文中使用的意思。所有的话都是可以理解的,但不是重点。

But I can't understand what "Multiple threads sharing the same transaction in a transaction scope will cause the following exception: 'Transaction context in use by another session.'" means. All words are understandable but not the point.

其实我可以线程之间共享的系统交易。甚至有特殊的机制,这 - DependentTransaction类Transaction.DependentClone方法

I actually can share a system transaction between threads. And there is even special mechanism for this - DependentTransaction class and Transaction.DependentClone method.

我试图重现从第一个帖子一个用例:

I'm trying to reproduce a usecase from the first post:

  1. 在主线程创建DTC事务,接收DependentTransaction(使用Transaction.Current.DependentClone在主线程创建
  2. 在子线程1报名在此DTC事务通过创建基于从属交易的交易范围(通过构造函数传递)
  3. 在子线程1打开一个连接
  4. 在子线程2征在DTC事务通过创建基于从属交易的交易范围(通过构造函数传递)
  5. 在子线程2打开一个连接

这样的code:

using System;
using System.Threading;
using System.Transactions;
using System.Data;
using System.Data.SqlClient;

public class Program
{
    private static string ConnectionString = "Initial Catalog=DB;Data Source=.;User ID=user;PWD=pwd;";

    public static void Main()
    {
        int MAX = 100;
        for(int i =0; i< MAX;i++)
        {
            using(var ctx = new TransactionScope())
            {
                var tx = Transaction.Current;
                // make the transaction distributed
                using (SqlConnection con1 = new SqlConnection(ConnectionString))
                using (SqlConnection con2 = new SqlConnection(ConnectionString))
                {
                    con1.Open();
                    con2.Open();
                }
                showSysTranStatus();

                DependentTransaction dtx = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete);
                Thread t1 = new Thread(o => workCallback(dtx));
                Thread t2 = new Thread(o => workCallback(dtx));
                t1.Start();
                t2.Start();
                t1.Join();
                t2.Join();

                ctx.Complete();
            }
            trace("root transaction completes");
        }
    }
    private static void workCallback(DependentTransaction dtx)
    {
        using(var txScope1 = new TransactionScope(dtx))
        {
            using (SqlConnection con2 = new SqlConnection(ConnectionString))
            {
                con2.Open();
                trace("connection opened");
                showDbTranStatus(con2);
            }
            txScope1.Complete();
        }   
        trace("dependant tran completes");
    }
    private static void trace(string msg)
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " : " + msg);
    }
    private static void showSysTranStatus()
    {
        string msg;
        if (Transaction.Current != null)
            msg = Transaction.Current.TransactionInformation.DistributedIdentifier.ToString();
        else
            msg = "no sys tran";
        trace( msg );
    }

    private static void showDbTranStatus(SqlConnection con)
    {
        var cmd = con.CreateCommand();
        cmd.CommandText = "SELECT 1";
        var c = cmd.ExecuteScalar();
        trace("@@TRANCOUNT = " + c);
    }
}

它没有根的TransactionScope的完全的电话。但是,错误是不同的: 未处理的异常:System.Transactions.TransactionInDoubtException:本次交易是个疑问。 ---> pired。之前完成操作已过或服务器超时期间没有响应。

It fails on Complete's call of root TransactionScope. But error is different: Unhandled Exception: System.Transactions.TransactionInDoubtException: The transaction is in doubt. ---> pired. The timeout period elapsed prior to completion of the operation or the server is not responding.

要总结一下:我想了解什么是事务上下文被另一个会话的手段,以及如何重现

To sum up: I want to understand what "Transaction context in use by another session" means and how to reproduce it.

推荐答案

退一步,并更专注于您的code和少的多线程信息流传。

Take a step back and focus more on your code and less in the multiple threads info floating around.

如果您的方案不涉及线程,它可能与你期望它。这不是封闭的片

If your scenario doesn't involve threading, it might relate to pieces that aren't closed as you expect it to.

也许SQL code您呼叫没有达到这个提交事务的指令。或者还有别的东西参与在这一水平。也许你使用一个SqlConnection实例设置在.NET code中的交易,并重新使用上使用的TransactionScope其​​他code表示相同的实例。尝试添加使用()指令在适当情况下,以确保一切都关闭,你指望了。

Maybe the sql code you are calling doesn't reach that commit transaction instruction. Or there is something else involved at that level. Maybe you used a SqlConnection instance setting the transaction in the .net code, and are reusing that same instance on the other code that uses the TransactionScope. Try adding using() instructions where appropriate, to make sure everything is closed as you expect it.

这篇关于什么是&QUOT的原因;而在另一个会话&QUOT使用事务上下文;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆