Database locking [transaction, transacciones}
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.
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
.
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.
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] |
---|---|---|---|
1 | Starts Transaction. | ||
2 | Starts Transaction. | ||
3 | Starts Transaction. | ||
4 | Updates row 2 in table A. | ||
5 | Attempts to update row 2 in table A. | ||
- | U2 Is Blocked by U1. | ||
6 | Attempts to delete row 2 in table A. | ||
- | U3 Is Blocked by U1. | ||
7 | Commits transaction | ||
- | Update completes. | U3 Is Blocked by U2. | |
8 | Rolls back transaction. | ||
- | Delete completes. | ||
9 | Commits transaction. |