Solución:
El bloqueo optimista es una estrategia en la que lee un registro, toma nota de un número de versión (otros métodos para hacer esto incluyen fechas, marcas de tiempo o sumas de verificación / hash) y verifica que la versión no haya cambiado antes de volver a escribir el registro. Cuando vuelve a escribir el registro, filtra la actualización en la versión para asegurarse de que sea atómica. (es decir, no se ha actualizado entre el momento en que verifica la versión y escribe el registro en el disco) y actualiza la versión de un solo golpe.
Si el registro está sucio (es decir, una versión diferente a la suya), cancela la transacción y el usuario puede reiniciarla.
Esta estrategia es más aplicable a sistemas de alto volumen y arquitecturas de tres niveles donde no necesariamente mantiene una conexión a la base de datos para su sesión. En esta situación, el cliente no puede mantener los bloqueos de la base de datos, ya que las conexiones se toman de un grupo y es posible que no esté utilizando la misma conexión de un acceso al siguiente.
El bloqueo pesimista es cuando bloquea el registro para su uso exclusivo hasta que haya terminado con él. Tiene una integridad mucho mejor que el bloqueo optimista, pero requiere que tenga cuidado con el diseño de su aplicación para evitar Deadlocks. Para utilizar el bloqueo pesimista, necesita una conexión directa a la base de datos (como suele ser el caso en una aplicación de servidor de cliente de dos niveles) o un ID de transacción disponible externamente que se puede utilizar independientemente de la conexión.
En el último caso, abre la transacción con el TxID y luego se vuelve a conectar con ese ID. El DBMS mantiene los bloqueos y le permite recuperar la sesión a través del TxID. Así es como funcionan las transacciones distribuidas que utilizan protocolos de confirmación de dos fases (como transacciones XA o COM +).
El bloqueo optimista se utiliza cuando no se esperan muchas colisiones. Cuesta menos hacer una operación normal, pero si ocurre la colisión, pagaría un precio más alto para resolverla ya que la transacción se cancela.
El bloqueo pesimista se utiliza cuando se anticipa una colisión. Las transacciones que violarían la sincronización simplemente se bloquean.
Para seleccionar el mecanismo de bloqueo adecuado, debe estimar la cantidad de lecturas y escrituras y planificar en consecuencia.
Cuando se trata de conflictos, tiene dos opciones:
- Puedes 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 actualización perdida puede ocurrir en el nivel de aislamiento de lectura confirmada.
En el diagrama de arriba podemos ver que Alice cree que puede retirar 40 de su 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 que Bob no pueda cambiar la cuenta.
En el diagrama anterior, tanto Alice como Bob adquirirán un bloqueo de lectura en el 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.
Porque 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 / exclusivo, y los bloqueos compartidos / de lectura evitan los bloqueos de escritura / exclusivos.
Solo después de que Alice haya confirmado su transacción y se haya liberado el bloqueo de lectura en el account
fila, Bob UPDATE
reanudará y aplicará el cambio. Hasta que Alice libere el bloqueo de lectura, la ACTUALIZACIÓN de Bob se bloquea.
Bloqueo optimista
El bloqueo optimista permite que se produzca el conflicto, pero lo detecta al aplicar la ACTUALIZACIÓN de Alice ya que la versión ha cambiado.
Esta vez, tenemos un adicional version
columna. los version
La 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.
Transacciones a nivel de aplicación
Los sistemas de bases de datos relacionales surgieron a finales de los 70 y principios de los 80 cuando un cliente, normalmente, se conectaba a un mainframe a través de una 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 hubiera detectado incluso si las transacciones de la base de datos usaran Serializable. Esto se debe a que las lecturas y escrituras se ejecutan en solicitudes HTTP separadas, por lo tanto, en diferentes transacciones de bases de datos.
Por lo tanto, el bloqueo optimista puede ayudarlo a evitar la pérdida de actualizaciones incluso cuando se utilizan transacciones a nivel de aplicación que también incorporan el tiempo de pensamiento del usuario.
Conclusión
El bloqueo optimista es una técnica muy útil y funciona bien incluso cuando se utilizan niveles de aislamiento menos estrictos, como Lectura confirmada, o cuando se ejecutan lecturas y escrituras en transacciones posteriores de la base de datos.
La desventaja del bloqueo optimista es que el marco de acceso a datos activará una reversión al detectar un OptimisticLockException
, perdiendo por lo tanto todo el trabajo que hemos realizado anteriormente por la transacción que se está ejecutando actualmente.
Cuanta más contienda, más conflictos y mayores son las posibilidades de abortar 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 filas de tabla como registros de índice.
Por esta razón, el bloqueo pesimista podría ser más adecuado cuando los conflictos ocurren con frecuencia, ya que reduce la posibilidad de deshacer transacciones.