2010-11-30 38 views
8

He estos dos excepción generada al intentar obtener datos de base de datos SQL en C#:SqlException: Punto muerto

System.Data.SqlClient.SqlException: Transacción (identificador de proceso 97) estaba en un punto muerto en los recursos de bloqueo con otro proceso y ha sido elegido como la víctima del punto muerto.

O

System.Data.SqlClient.SqlException: transacción (ID de proceso 62) quedó en interbloqueo en recursos de bloqueo con otro proceso y ha sido elegido como víctima del interbloqueo.

O

System.Data.SqlClient.SqlException: transacción (ID de proceso 54) quedó en interbloqueo en recursos de bloqueo con otro proceso y ha sido elegido como víctima del interbloqueo. Vuelva a ejecutar la transacción.

este es el código:

using (SqlConnection con = new SqlConnection(datasource)) 
       { 
        SqlCommand cmd = new SqlCommand("Select * from MyTable Where ID='1' ", con); 
        cmd.CommandTimeout = 300; 
        con.Open(); 
        SqlDataAdapter adapter = new SqlDataAdapter(cmd); 
        DataSet ds = new DataSet(); 
        adapter.Fill(ds); 
        con.Close(); 
        return ds.Tables[0]; 
       } 

Estos Evry tiempo hapened.

¿Alguna idea de cómo se pueden resolver?

+2

¿Recibió esta excepción una vez o sucede cada vez que prueba? –

+3

¿Podría mostrar su consulta? –

+0

Estos le dicen cada vez que lo intento. –

Respuesta

7

No es que esto va a ayudar al problema de bloqueo, pero se debe desechar sus otros objetos IDisposable al igual que lo está decida deshacerse de la SqlConnection como tal:

using (SqlConnection con = new SqlConnection(datasource)) 
    using (SqlCommand cmd = new SqlCommand("Select * from MyTable Where ID='1' ", con)) 
    { 
     cmd.CommandTimeout = 300; 
     con.Open(); 
     using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) 
     using (DataSet ds = new DataSet()) 
     { 
      adapter.Fill(ds); 
      return ds.Tables[0]; 
     } 
    } 

Usted puede ser capaz de evitar la cerradura con una pista de bloqueo en su consulta así:

Select * from MyTable with (nolock) Where ID='1' 

Espero que esto ayude.

3

Básicamente, el modelo de simultaneidad del servidor SQL lo hace para que nunca pueda evitar esta excepción (por ejemplo, las transacciones completamente independientes pueden bloquearse si bloquean la misma página de índice o algo así). Lo mejor que puede hacer es mantener sus transacciones cortas para reducir la probabilidad, y si obtiene la excepción, haga lo que dice y vuelva a intentar la transacción.

+0

Estás confundiendo los conceptos de bloqueo y bloqueo. No es verdad que esta excepción sea inevitable. –

+0

No, no lo soy. Si usa el bloqueo predeterminado (a veces rowlock, a veces pagelock), es fácil ver que dos transacciones no relacionadas pueden atascarse accidentalmente entre sí (al menos si actualizan dos tablas dentro de la transacción y no utiliza pistas para asegurarse de que siempre se leen en el mismo orden). Para el caso rowlock, es menos obvio, pero los índices pueden morderlo aquí. – erikkallen

16

Hay un par de cosas que puede hacer para disminuir la cantidad de interbloqueos que recibe, y algunas cosas que puede hacer para eliminarlos por completo.

En primer lugar, inicie el Analizador de SQL Server y dígale que le proporcione un deadlock graph. La ejecución de este seguimiento le indicará la otra consulta que está en conflicto con la suya. Su consulta es bastante simple, aunque dudo seriamente que tenga una consulta SELECT * en una tabla llamada MyTable en su sistema ...

De todos modos, armado con el gráfico de interbloqueo y la otra consulta, debería ser capaz de decir qué recursos estan bloqueados La solución clásica es cambiar el orden de ambas consultas de modo que se acceda a los recursos en el mismo orden, esto evita ciclos.

Otras cosas que puede hacer:

  • velocidad hasta sus consultas mediante, entre otras cosas, la aplicación de los índices correctos para ellos.
  • Habilite el aislamiento de instantáneas en la base de datos y use SET TRANSACTION ISOLATION LEVEL SNAPSHOT en sus transacciones, según corresponda. También habilite read committed with row-versioning. En muchos casos, esto es suficiente para eliminar la mayoría de los puntos muertos por completo. Lea sobre los niveles de aislamiento de transacciones. Understand qué estás haciendo.