2012-02-29 11 views
7

Implementé SqlTransaction en C# para comenzar, confirmar y retrotraer la transacción. Todo va bien, pero tengo algún problema al acceder a esas tablas que están conectadas durante la transacción. No pude leer la tabla durante la transacción (la tabla que está en transacción). Mientras buscaba sobre esto, descubrí que sucede debido a un bloqueo exclusivo. Cualquier selección posterior en esos datos a su vez tiene que esperar a que se libere el bloqueo exclusivo. Luego, he revisado cada nivel de aislamiento proporcionado por SqlTransaction, pero no funcionó. Por lo tanto, debo liberar el bloqueo exclusivo durante la transacción para que otros usuarios puedan tener acceso a esa tabla y puedan leer los datos. ¿Hay algún método para lograr esto? Gracias de antemano.Nivel de aislamiento en Sql Transacción

Aquí está mi código C# para la transacción

try 
{ 
    SqlTransaction transaction = null;       
    using (SqlConnection connection=new SqlConnection(Connection.ConnectionString)) 
    { 
     connection.Open(); 
     transaction=connection.BeginTransaction(IsolationLevel.Snapshot,"FaresheetTransaction");    
     //Here all transaction occurs 
     if (transaction.Connection != null) 
     {  
       transaction.Commit(); 
       transaction.Dispose(); 
     } 
    } 
} 
catch (Exception ex) 
{ 
    if (transaction.Connection != null) 
     transaction.Rollback(); 
    transaction.Dispose(); 
} `       

Este código está trabajando muy bien, pero el problema es que cuando accedo a los datos de las tablas (aquellos visitada durante la transacción) en el momento de la transacción. Se accede a las tablas por otras partes de la aplicación. Entonces, cuando traté de leer datos de la tabla, arroja una excepción.

+1

¿Cuál es su intención aquí? No se lo tome el bloqueo al actualizar? o para que otros lectores ignoren los bloqueos (que están ahí por muy buenas razones) –

+1

No deseo tener un bloqueo en la tabla transacted para otros usuarios ... la transacción puede ser de larga duración porque en el momento de la transacción, diez de miles de datos se insertan en la tabla, por lo que probablemente lleve mucho tiempo ... Por lo tanto, en el período de tran saction, quiero que otro usuario tenga acceso a esa tabla y pueda leer datos ....... –

Respuesta

14

Una transacción SQL es, por diseño, ACID. En particular, es la "I" la que lo está perjudicando aquí; esto es diseñado para evitar que otras conexiones vean el estado intermedio inconsistente.

Una conexión a la lectura individual puede optar por ignorar esta regla mediante la indirecta NOLOCK, o el nivel READ UNCOMMITTED aislamiento, pero suena como que queremos es que la escritura conexión al no tener cerraduras. Bueno, eso no va a suceder.

Sin embargo, lo que fuerza ayuda es para que los lectores utilizan instantánea aislamiento, lo que logra el aislamiento sin que el lector teniendo cerraduras (examinado, como su nombre indica, un shapshot punto en el tiempo del estado consistente cuando comenzó la transacción).

Sin embargo, la OMI que haría mejor a mirar a cualquiera:

  • múltiple, más granular, las transacciones del escritor
  • realizar el trabajo en una tabla de ensayo (una copia paralela de los datos) , entonces la fusión que en los datos reales en unas pocas masas insertar/actualizar/borrar operaciones, minimizando el tiempo de transacción

la primera es más simple.

El hecho simple es: si toma una transacción de larga duración que opera en una gran cantidad de datos, va a estar causando problemas. Es por eso que no hagas eso. El sistema está funcionando correctamente.

+2

su segunda solución es más o menos lo que el aislamiento de instantáneas está haciendo por usted cuando se usa para una transacción que realiza escrituras;) – ntziolis

+0

He utilizado el nivel de aislamiento de instantáneas, pero nuevamente da el mismo problema ....En realidad, funciona cuando uso "select * from tbl_name with (nolock)" pero esta selección no es apropiada para mí debido a: 1. Ya muestra los datos de la transacción que aún no se ha confirmado. 2. la tabla ya ha sido consultada desde la aplicación, por lo que no es factible que realice todas las consultas en el código y lo cambie ...... –

+1

@ akash88 es el ** lector ** que necesita usar el aislamiento de instantáneas; si no fue de ayuda, entonces me pregunto si simplemente no has habilitado el aislamiento de instantáneas. Pero, fundamentalmente, estás tratando de hacer algo que está en contra del sistema. Un ejemplo equivalente podría ser "Tengo un archivo grande abierto mientras reescribo fragmentos grandes de él; no quiero permitir el acceso compartido porque luego los lectores verían las ediciones en curso, pero no el archivo está bloqueado hasta que cierre ¡Cómo lo soluciono! respuesta: no lo haces; diseñas el sistema de manera diferente. –

3

Intente ejecutar sus lecturas también en una transacción y utilice el nivel de aislamiento READ UNCOMMITTED. Esto evitará que la lectura de estar encerrado, pero puede producir resultados no válidos:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED  
BEGIN TRANSACTION 

SELECT * FROM Table 

COMMIT TRANSACTION 

Hay una idea errónea de que se trata de transacciones/niveles de aislamiento sólo importa la hora de escribir, cuando en realidad es igualmente importante cuando se lee.

+0

Gracias por su respuesta ..... He usado todo tipo de nivel de aislamiento, pero podría funcionar con mi escenario. .. En realidad, lo estoy usando en C# usando el método BeginTransaction() de SqlTransaction .... Quiero dar acceso a otros usuarios para esas tablas que están esperando transacciones ... Pero, en cada nivel de aislamiento, exclusivo se está cerrando ........ –

+0

Si está escribiendo en la tabla, los bloqueos exclusivos son obligatorios. La única excepción es cuando utiliza la instantánea de nivel de aislamiento, pero hasta donde sé, solo está disponible a partir de sql 2008. Por lo tanto, la única forma de permitir lecturas es mediante el uso de niveles de aislamiento sin leer o de caos durante las lecturas como se describe anteriormente – ntziolis

+0

comprobado, el aislamiento de instantáneas ya está disponible en SQL 2005, así que ahí lo tienes. Utilice el aislamiento de instantáneas al escribir y debería estar listo para comenzar. Como parece que solo estás leyendo en las otras operaciones, no debería haber problemas con eso. – ntziolis

2

El problema no está en el nivel de escritura en la base de datos sino en el nivel de valores de lectura. Está intentando leer valores que se están insertando. Trate de cambiar su consulta de selección a continuación:

select * from your_table_with_inserts with (nolock) 

sin embargo éste anula el nivel de aislamiento de transacción actual y puede causar lecturas sucias.

Entonces la pregunta es: si está utilizando la transacción en todas las consultas o solo inserta/actualiza?

1

@ AKASH88, SNAPSHOT nivel de aislamiento es lo que está buscando.

Usted dice que incluso con SNAPSHOT no está funcionando como se esperaba, está ocurriendo bloqueo exclusivo, puedo entender que tuve el mismo problema.

Asegúrese de no solo habilitar SNAPSHOT en las opciones de la base de datos, sino también READ COMMISSED SNAPSHOT debe estar encendido.

enter image description here

Esta es SQL Server 2008, por lo que es todavía incierto si esta respuesta le ayudará :(

Saludos!

Cuestiones relacionadas