iberck
11/6/2015 - 3:16 AM

Pesimistic y Optimistic Locking

Pesimistic y Optimistic Locking

Optimistic Locking

Sirve para mantener cierto nivel de atomicidad, si 2 usuarios modifican el mismo objeto al mismo tiempo y lo guardan, ¿cuál de los dos debe ser guardado?

Hibernate crea una columna llamada version (y grails una propiedad). Cada que un objeto es guardado revisa que su versión sea la misma, si no lo es lanza una StaleObjectException.Por lo tanto este esquema previene que un usuario guarde un objeto que fue guardado mientras lo estaba modificando porque tendría una versión diferente y lanzaría una excepción.

La ventaja de este esquema es que es muy eficiente, la desventaja es que se debe estar cachando una excepción al guardar los objetos para saber si se está intentando actualizar un objeto con una versión distinta y poder recuperarse del error (tal vez volver a pedir los datos al usuario mostrando los nuevos).

Si dos usuarios guardan al mismo tiempo un objeto, uno de los dos se debe guardar antes que el otro incrementando así su versión, luego cuando el segundo objeto se intenente guardar lanzará la excepción porque la versión no es mayor a la actual.

La columna versión comienza siempre en 0 y cada que se guarda el objeto, se va incrementando en 1 la versión

By default GORM classes are configured for optimistic locking, which is a feature of Hibernate that involves storing an incrementing version in the table. This value is only updated in the database when the Hibernate session is flushed.

Pessimistic Locking

Es equivalente a hacer un select * from update de SQL, obtiene y bloquea la fila en la bd.

def aeropuerto = Aeropuerto.get(1)
aeropuerto.lock() // bloquea la fila para hacer el update
airport.name='Mex'
airport.save() // Grails se encarga de soltar el lock cuando se haga commit de la tx

El anterior código es bueno pero podría causar que otro thread interfiera y 2 usuarios modifiquen el objeto al mismo tiempo, para evitarlo se utiliza el lock a nivel de clase:

def aeropuerto = Aeropuerto.lock(10)
aeropuerto.name='Mex'
aeropuerto.save()

También se puede utilizar lock al hacer queries o al utililizar criterias.

def aeropuerto = Aeropuerto.findByName('Mex', [lock:true])

El siguiente recurso indica el propósito del pessimistic locking: https://stackoverflow.com/questions/8113301/what-is-the-purpose-of-session-lock-method-in-hibernate

Grails optimistic y pessimistic

Por defecto Grails utiliza el esquema optimistic.