iberck
9/9/2015 - 1:30 PM

Database locking [transaction, transacciones}

Database locking [transaction, transacciones}

Database locking

Si TxA escribe datos y TxB lee al mismo tiempo dichos datos, el valor que obtenga depende del nivel de aislamiento que tenga establecido TxB.

Si TxA modifica una fila (update/delete) y TxB desea modificar al mismo tiempo la misma filas, el SGBD utiliza un mecanismo de locks automáticos para garantizar la integridad de los datos.

Locks automáticos (update/delete)

Por defecto cuando TxA actualiza o elimina una fila pondrá un candado (lock) sobre dicha fila indicando que solo TxA puede manipular la fila hasta que haga commit/rollback. Si TxB quiere utilizar la misma fila, se quedará en un estado de espera (waiting...) hasta que TxA haga commit/rollback, una vez que termine TxA TxB tomará el lock de dicha fila y continuará su ejecución en el lugar donde se quedó.

Las bases de datos también utilizan locks automáticos cuando se utiliza la sentencia SELECT FOR UPDATE.

Ejemplo

Imagine 2 transacciones (TxA y TxB) concurrentes que se pelean por llegar a la fila:

update survey_folio set last_folio=last_folio+1 where s_id_survey=1

La transacción que tome primero el update tendrá el lock sobre la fila y lo soltará hasta hacer commit/rollback, las demás transacciones que lleguen a esta fila y quieran un folio de la misma encuesta tendrán que esperar a que termine la primer transacción (quedan en estado waiting). De esta forma se garantiza la integridad de datos creando siempre folios sucesivos sin repetición.

Si se está ejecutando la sentencia SQL desde hibernate, será necesario lanzar un sess.flush() para garantizar que se ejecute la sentencia y la transacción obtenga el bloqueo:

SQLQuery sqlQuery = sess.createSQLQuery("update survey_folio set last_folio=last_folio+1 where s_id_survey=:idSurvey");
sqlQuery.setInteger("idSurvey", survey.getIdSurvey());
sqlQuery.executeUpdate();
sess.flush(); // enviar el update a la base de datos para que se realice el bloqueo.

Ejemplo de locking

The example below illustrates the most common and logical form of transactional locking. In this case, we have 3 transactions that are all attempting to make changes to a single row in Table A. U1 obtains an exclusive lock on this table when issuing the first update statement. Subsequently, U2 attempts to update the same row and is blocked by U1’s lock. U3 also attempts to manipulate this same row, this time with a delete statement, and that is also blocked by U1’s lock.

When U1 commits its transaction, it releases the lock and U2’s update statement is allowed to complete. In the process, U2 obtains an exclusive lock and U3 continues to block. Only when U2’s transaction is rolled back does the U3’s delete statement complete.

This example shows how the DBMS is maintaining consistency and isolation.

[Time][User 1 Actions][User 2 Actions][User 3 Actions]
1Starts Transaction.
2Starts Transaction.
3Starts Transaction.
4Updates row 2 in table A.
5Attempts to update row 2 in table A.
-U2 Is Blocked by U1.
6Attempts to delete row 2 in table A.
-U3 Is Blocked by U1.
7Commits transaction
-Update completes.U3 Is Blocked by U2.
8Rolls back transaction.
-Delete completes.
9Commits transaction.