Estoy buscando una descripción de la raíz de este error: "contexto de transacción en uso por otra sesión".Cuál es el motivo de "contexto de transacción en uso por otra sesión"
Lo obtengo a veces en uno de mis unittests así que no puedo proporcionar el código de repro. Pero me pregunto qué es el motivo "por diseño" del error.
ACTUALIZACIÓN: el error vuelve como SqlException de SQL Server 2008. Un lugar donde aparece el error parece ser de subproceso único. Pero probablemente tengo interacciones unittest, ya que recibo el error donde ejecuto varias pruebas a la vez (MSTest en VS2008sp1). Pero la prueba no se parece a:
- crear un objeto y guardar dentro de DB-transacción (commit)
- crear TransactionScope
- intentar abrir una conexión - aquí llego SqlException con tales StackTrace:
.
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()
he encontrado estos mensajes:
- 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
pero no puedo entender lo que "hilos múltiples compartiendo la misma transacción en un ámbito de transacción causará la siguiente excepción: 'Contexto de transacción en uso por otra sesión.' " significa. Todas las palabras son comprensibles, pero no el punto.
De hecho, puedo compartir una transacción del sistema entre subprocesos. Y hay incluso un mecanismo especial para esto: clase DependentTransaction y método Transaction.DependentClone.
Estoy intentando reproducir un caso de uso a partir del primer mensaje:
- hilo principal crea transacción DTC, recibe DependentTransaction (creada usando Transaction.Current.DependentClone en el hilo principal
- hilo hijo 1 enlista en esta transacción DTC al crear un ámbito de transacción basado en la transacción dependiente (aprobada mediante constructor)
- El hilo secundario 1 abre una conexión
- El hilo secundario 2 se alista en la transacción DTC al crear un alcance de transacción bas ed de la transacción dependiente (pasado a través de constructor)
- hilo Niño 2 abre una conexión
con dicho código:
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);
}
}
Se produce un error en la llamada de TransactionScope completa de raíz. Pero el error es diferente: Excepción no controlada: System.Transactions.TransactionInDoubtException: la transacción está en duda. ---> pired. El período de tiempo de espera transcurrido antes de la finalización de la operación o el servidor no responde.
En resumen: quiero entender qué significa "Contexto de transacción en uso por otra sesión" y cómo reproducirlo.
Un pequeño punto: ¿estás seguro de que tienes una transacción distribuida? Hace 2 conexiones abiertas: con1.Open(); con2.Open(); Pero la cadena de connestion es la misma y está usando Sql2008. AFAIK si usa Sql2008 Y la misma cadena de conexión, la transacción no escalará a distribuida. Sigue siendo "local". Mis 2 centavos. –
No, la apertura de dos conexiones simultáneas siempre conduce a una transacción distribuida. No importa que tengan las mismas cadenas de conexión o no – Shrike
mi error. Lo siento. –