Si no especificas las opciones de una transacción, esta será: READ WRITE, SNAPSHOT, WAIT

Siempre debes especificar las opciones de una transacción, salvo que quieras las opciones por defecto. El SET TRANSACTION solamente afecta a la transacción actual, las transacciones que escribas a continuación continuarán con las opciones por defecto (o sea que todas serán READ WRITE, SNAPSHOT, WAIT a no ser que especifiques otra cosa).

Veamos un ejemplo:

  • La transacción T1 hace un UPDATE a una fila (y al hacer eso la bloquea, nadie más puede actualizarla hasta que finalice la transacción T1)
  • La transacción T1 no hace todavía ni el COMMIT ni el ROLLBACK a esa fila, por lo tanto la transacción T1 queda abierta
  • La transacción T2 hace un UPDATE a la misma fila de la transacción T1

Lo que ocurrirá a continuación depende de dos cosas: el modo de bloqueo (que puede ser WAIT o NO WAIT) y el aislamiento (que puede ser READ COMMITTED, SNAPSHOT, SNAPSHOT TABLE STABILITY)

Si el aislamiento de la transacción T2 es READ COMMITTED (que es la opción recomendada cuando se están ingresando datos):

  • Si el “modo de bloqueo” de la transacción T2 es WAIT, la transacción T2 se queda esperando hasta que la transacción T1 finalice con COMMIT o con ROLLBACK
    • Si la transacción T1 finaliza con un COMMIT, la transacción T2 puede ahora finalizar con un COMMIT o con un ROLLBACK, como quiera
    • Si la transacción T1 finaliza con un ROLLBACK, la transacción T2 puede ahora finalizar con un COMMIT o con un ROLLBACK, como quiera
  • Si el “modo de bloqueo” de la transacción T2 es NO WAIT, entonces la transacción T2 inmediatamente recibe el error “deadlock – lock conflict on no wait transaction”. A esta situación se la conoce como bloqueo mortal.

Fin si

Si el aislamiento de la transacción T2 es SNAPSHOT (que es la opción por defecto y la recomendada cuando se usa el comando SELECT):

  • Si el “modo de bloqueo” de la transacción T2 es WAIT, la transacción T2 se queda esperando hasta que la transacción T1 finalice con COMMIT o con ROLLBACK
    • Si la transacción T1 finaliza con un COMMIT, la transacción T2 finaliza con el error “deadlock – update conflicts with concurrent update”, o sea con un bloqueo mortal.
    • Si la transacción T1 finaliza con un ROLLBACK, la transacción T2 puede finalizar con un COMMIT o con un ROLLBACK, como quiera
  • Si el “modo de bloqueo” de la transacción T2 es NO WAIT, entonces la transacción T2 inmediatamente recibe el error “deadlock – update conflicts with concurrent update”, que es también un bloqueo mortal.

Si ocurre un bloqueo mortal lo único que puedes hacer es un ROLLBACK y luego, si lo deseas, empezar una nueva transacción (T3) para intentar grabar nuevamente esos datos.
Mientras la transacción T1 no haga ni un COMMIT ni un ROLLBACK, la transacción T2 no podrá actualizar la fila que fue bloqueada por la transacción T1

Fin si

Si el aislamiento de la transacción T2 es SNAPSHOT TABLE STABILITY (el cual no deberías usar en Firebird, salvo rarísimas excepciones):

  • Si el “modo de bloqueo” de la transacción T2 es WAIT, la transacción T2 se queda esperando hasta que la transacción T1 finalice con COMMIT o con ROLLBACK.
    • Si la transacción T1 termina con un COMMIT, la transacción T2 recibe un bloqueo mortal.
    • Si la transacción T1 termina con un ROLLBACK, la transacción T2 puede terminar con un COMMIT o con un ROLLBACK, como quiera
  • Si el “modo de bloqueo” de la transacción T2 es NO WAIT, entonces:
    • La transacción T2 recibe inmediatamente un bloqueo mortal.

Fin si

Opciones recomendadas:

  • En los programas donde se insertan/borran/actualizan datos: READ WRITE, READ COMMITTED, WAIT
  • En los programas donde se consultan datos: READ ONLY, SNAPSHOT, WAIT
Anuncios