Soy parte de un equipo que está creando un sitio web basado en ADO.NET. A veces tenemos varios desarrolladores y una herramienta de prueba automatizada que trabaja simultáneamente una copia de desarrollo de la base de datos.Usando IsolationLevel.Snapshot pero DB todavía está bloqueando
Utilizamos el nivel de aislamiento de instantáneas, que, según mi leal saber y entender, utiliza concurrencia optimista: en lugar de bloquear, espera lo mejor y lanza una excepción si intentas comprometer una transacción si las filas afectadas han sido alteradas por otra parte durante la transacción.
Para utilizar el nivel de aislamiento de instantánea que utilizamos:
ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;
y en C#:
Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);
Tenga en cuenta que IsolationLevel fotografiado no es lo mismo que ReadCommitted instantánea, que también hemos intentado, pero no están usando actualmente.
Cuando uno de los desarrolladores ingresa al modo de depuración y detiene la aplicación .NET, mantendrá una conexión con una transacción activa durante la depuración. Ahora, espero que esto no sea un problema; después de todo, todas las transacciones usan el nivel de aislamiento de instantáneas, por lo que, mientras una transacción está en pausa, otras transacciones deberían poder continuar normalmente ya que la transacción detenida no contiene bloqueos. Por supuesto, cuando la transacción pausada finaliza, es probable que detecte un conflicto; pero eso es aceptable siempre y cuando otros desarrolladores y las pruebas automatizadas puedan avanzar sin obstáculos.
Sin embargo, en la práctica, cuando una persona detiene una transacción durante la depuración, todos los demás usuarios de DB que intentan acceder a las mismas filas se bloquean a pesar de usar el nivel de aislamiento de instantáneas.
¿Alguien sabe por qué ocurre esto y/o cómo puedo lograr una concurrencia verdaderamente optimista (sin bloqueo)?
La resolución (una desafortunada para mí): Remus Rusanu señaló que los escritores siempre bloquean a otros escritores; esto está respaldado por MSDN - no acaba de salir y decirlo, pero solo menciona evitar bloqueos lector-escritor. En resumen, el comportamiento que deseo no está implementado en SQL Server.
Este comportamiento es poco probable en producción. Por otro lado, la versión de desarrollo es bastante importante, y estaría dispuesto a hacer cambios de código si eso facilita el desarrollo. Desafortunadamente, un estilo de bloqueo "svn-esque" (esperar lo mejor y simplemente fallar en el conflicto) no parece implementarse. La capacidad de tener transacciones complejas y de larga duración sin bloquear todas las pequeñas transacciones aún sería útil; como es el caso, utilizamos menos transacciones que sean ideales solo para evitar el bloqueo. –
No hay una bala de plata. Pero si se encuentra a menudo bloqueado en escritura y escritura, debe considerar por qué ocurre esto, por qué diferentes 'solicitudes' provocan actualizaciones de los mismos datos. Tal vez pueda particionar mejor su aplicación, disminuir la probabilidad de superposición. Tal vez algunas actualizaciones se pueden diferir, poner en cola en una mesa de trabajo durante la transacción del usuario (enque/dequeue se puede hacer sin bloque, con cuidado) y luego procesadas por procesos por lotes dedicados. Además, asegúrese de que todas las transacciones solo bloqueen el mínimo necesario (sin bloqueos de página/tabla, sin escalamiento, sin escaneos inútiles de tablas). –