Cuando se trata de conflictos, tiene dos opciones:
- Puede intentar evitar el conflicto, y eso es lo que hace el bloqueo pesimista.
- O bien, puede permitir que ocurra el conflicto, pero debe detectarlo al confirmar sus transacciones, y eso es lo que hace Optimistic Locking.
Ahora, consideremos la siguiente anomalía de actualización perdida :
La anomalía de la actualización perdida puede ocurrir en el nivel de aislamiento de lectura comprometida .
En el diagrama de arriba podemos ver que Alice cree que puede retirar 40 de ella, account
pero no se da cuenta de que Bob acaba de cambiar el saldo de la cuenta, y ahora solo quedan 20 en esta cuenta.
Bloqueo pesimista
El bloqueo pesimista logra este objetivo al tomar un bloqueo compartido o de lectura en la cuenta para evitar que Bob cambie la cuenta.
En el diagrama anterior, tanto Alice como Bob adquirirán un bloqueo de lectura en la account
fila de la tabla que ambos usuarios han leído. La base de datos adquiere estos bloqueos en SQL Server cuando utiliza lectura repetible o serializable.
Debido a que tanto Alice como Bob han leído el account
con el valor PK de 1
, ninguno de ellos puede cambiarlo hasta que un usuario libere el bloqueo de lectura. Esto se debe a que una operación de escritura requiere una adquisición de bloqueo de escritura / exclusiva, y los bloqueos compartidos / leídos evitan bloqueos de escritura / exclusivos.
Solo después de que Alice haya comprometido su transacción y se haya liberado el bloqueo de lectura en la account
fila, Bob UPDATE
reanudará y aplicará el cambio. Hasta que Alice libere el bloqueo de lectura, la ACTUALIZACIÓN de Bob se bloquea.
Para obtener más detalles sobre cómo los marcos de acceso a datos utilizan el soporte de bloqueo pesimista de la base de datos subyacente, consulte este artículo .
Bloqueo optimista
El bloqueo optimista permite que ocurra el conflicto, pero lo detecta al aplicar la ACTUALIZACIÓN de Alice a medida que la versión ha cambiado.
Esta vez, tenemos una version
columna adicional . La version
columna se incrementa cada vez que se ejecuta UPDATE o DELETE, y también se usa en la cláusula WHERE de las declaraciones UPDATE y DELETE. Para que esto funcione, necesitamos emitir SELECT y leer el actual version
antes de ejecutar UPDATE o DELETE, de lo contrario, no sabríamos qué valor de versión pasar a la cláusula WHERE o incrementar.
Para obtener más detalles sobre cómo los marcos de acceso a datos implementan un bloqueo optimista, consulte este artículo .
Transacciones a nivel de aplicación
Los sistemas de bases de datos relacionales han surgido a fines de los años 70 y principios de los 80, cuando un cliente, típicamente, se conectaba a una unidad central a través de un terminal. Es por eso que todavía vemos que los sistemas de bases de datos definen términos como la configuración de SESIÓN.
Hoy en día, a través de Internet, ya no ejecutamos lecturas y escrituras en el contexto de la misma transacción de base de datos, y ACID ya no es suficiente.
Por ejemplo, considere el siguiente caso de uso:
Sin un bloqueo optimista, no hay forma de que esta actualización perdida se haya detectado incluso si las transacciones de la base de datos utilizaran Serializable. Esto se debe a que las lecturas y escrituras se ejecutan en solicitudes HTTP separadas, por lo tanto, en diferentes transacciones de la base de datos.
Por lo tanto, el bloqueo optimista puede ayudarlo a evitar Actualizaciones Perdidas incluso cuando utiliza transacciones a nivel de aplicación que también incorporan el tiempo de reflexión del usuario.
Para obtener más detalles sobre las transacciones lógicas o de nivel de aplicación, consulte este artículo .
Conclusión
El bloqueo optimista es una técnica muy útil, y funciona bien incluso cuando se usan niveles de aislamiento menos estrictos, como lectura confirmada, o cuando las lecturas y escrituras se ejecutan en transacciones de bases de datos posteriores.
La desventaja del bloqueo optimista es que el marco de acceso a datos desencadenará una reversión al capturar una OptimisticLockException
, por lo tanto, perderá todo el trabajo que hemos realizado anteriormente en la transacción que se está ejecutando actualmente.
A mayor contención, más conflictos y mayores posibilidades de abortar las transacciones. Las reversiones pueden ser costosas para el sistema de base de datos, ya que necesita revertir todos los cambios pendientes actuales que pueden involucrar tanto las filas de la tabla como los registros de índice.
Por esta razón, el bloqueo pesimista puede ser más adecuado cuando los conflictos ocurren con frecuencia, ya que reduce la posibilidad de revertir las transacciones.