Cada transacción tiene un número que la identifica de forma exacta, no pueden existir dos transacciones con el mismo número y en el mismo momento.

Identificador de la transacción

Al número que identifica a la transacción se le conoce como TID (Transaction Identificator)

Estados de las transacciones

Una transacción solamente puede estar en uno de estos estados:

  • Confirmada. Significa que la transacción finalizó con un COMMIT
  • Revertida. Significa que la transacción finalizó con un ROLLBACK
  • Activa. Significa que la transacción aún no finalizó ni con un COMMIT ni con un ROLLBACK ni está en limbo
  • Limbo. Significa que falló el segundo COMMIT. En transacciones que involucran a dos bases de datos hay que hacer dos COMMIT, uno para cada Base de Datos. Si el primer COMMIT finalizó exitosamente y el segundo COMMIT falló entonces la transacción está en limbo.

Transacciones interesantes

Hay algunas transacciones que para el Firebird son de interés, y son las siguientes:

  • Oldest transaction (la transacción más antigua). Es la transacción más antigua que no finalizó con un COMMIT. Eso significa que puede estar revertida, activa o en limbo. Las transacciones confirmadas (o sea, las que finalizaron con un COMMIT) ya no le interesan al Firebird. ¿Por qué no? porque ya han sido guardadas exitosamente y ya nada le queda para hacer con ellas. A la Oldest transaction se la conoce también como la Oldest Interesting Transaction (la más antigua transacción interesante) y se la representa con las letras OIT.
  • Oldest active transaction (la transacción activa más antigua). Es la más antigua transacción que no finalizó ni con un COMMIT ni con un ROLLBACK y no está en limbo. Eso significa que el usuario en este momento tiene a la transacción abierta y está haciendo algo con ella (insertando, modificando, borrando, consultando, ejecutando un stored procedure). Se la representa con las letras OAT.
  • Oldest snapshot transaction  (la transacción instantánea más antigua). Es la transacción más antigua cuya basura no puede ser recolectada. Una transacción deja basura cuando modifica una fila, borra una fila, o finaliza con un ROLLBACK. Lo normal es que esa basura pueda ser recolectada y entonces este número es igual al de la OAT, ese es el caso más común. A la Oldest snapshot transaction se la representa con las letras OST.
  • Next transaction (siguiente transacción). Es el número que tendrá la siguiente transacción.

Barrido automático

El sweep (barrido, de barrer con una escoba) puede estar activado o desactivado. Si está activado entonces empieza cuando la diferencia entre la OST y la OIT es mayor que el sweep interval (intervalo del barrido). Por ejemplo:

OST = 45.201

OIT = 25.200

Sweep interval = 20.000

OST – OIT = 45.201 – 25.200 = 20.001

Como el resultado de OST – OIT (que en este ejemplo es 20.001) es mayor que el intervalo del sweep (que en este ejemplo es 20.000) entonces empieza el sweep.

¿Que hace el sweep?

Elimina permanentemente de la Base de Datos toda la basura que fueron dejando las transacciones. Una transacción deja basura cuando modifica una fila, borra una fila, o finaliza con un ROLLBACK.

¿Es beneficioso el sweep?

Sí, muy beneficioso porque cuando finaliza la Base de Datos queda más limpia y en consecuencia conectarse a ella será más rápido y realizar operaciones en ella (INSERT, UPDATE, DELETE, FETCH, SELECT, EXECUTE PROCEDURE) también será más rápido.

Detectando problemas

Si la diferencia entre la OAT y la Next Transaction aumenta y aumenta eso significa que alguna transacción no está terminando con un COMMIT y por lo tanto está aumentando la cantidad de basura. Cuando la diferencia entre la OAT y la Next Transaction sea grande («diferencia grande» depende de tu hardware y de tu software) notarás que cada vez toma más tiempo conectarse a la Base de Datos y realizar operaciones en ella. En estos casos lo correcto es utilizar el programa GFIX.EXE para hacer un sweep manual.

Reinicio de los identificadores de las transacciones. Caso 1

Cada vez que haces un ciclo backup/restore los números de los identificadores de las transacciones vuelven a empezar en uno. Por ejemplo:

NT = 65.920

Se hace un ciclo backup/restore y en la Base de Datos restaurada se ve que:

NT= 387

¿Qué pasó, por qué disminuyó la NT? Porque a todas las transacciones confirmadas el Firebird les asignó un número (el mismo número les asignó a todas las transacciones confirmadas) y a la basura la eliminó, o sea que dejó en la Base de Datos solamente las transacciones que previamente habían finalizado con un COMMIT.

¿Qué implica que los números de las transacciones interesantes cambien después de un ciclo backup/restore?

Que jamás deberías usar esos números dentro de tu programa para identificar a las transacciones entre una conexión y otra. O sea que tus programas no deberían depender de los números de las transacciones entre dos conexiones distintas. Dentro de la misma conexión no hay problema, el identificador no cambiará. Por ejemplo, una transacción está haciendo un INSERT en la tabla PRODUCTOS y esa transacción tiene el número 527. Puedes usar ese número 527 para identificarla sin problema. Pero si el usuario se desconectó de la Base de Datos y volvió a conectarse ya no deberías usar el número 527 porque ahora la transacción que hizo el INSERT a la tabla PRODUCTOS podría tener otro número (si se hizo un ciclo backup/restore entre ambas conexiones).

Reinicio de los identificadores de las transacciones. Caso 2

Hay otro caso en el cual el número de la Next Transaction no aumenta.

Los identificadores de las transacciones se guardan internamente como números de tipo INTEGER. Los números de tipo INTEGER pueden, como máximo, llegar hasta 2.147.483.647.

Entonces, ¿qué pasa cuando la Next Transaction alcanza a ese número?

Que ya no se puede seguir usando esa Base de Datos. Imposible. La conexión siempre será denegada.

¿Y cuál es la solución?

Hacer un ciclo backup/restore y usar la Base de Datos restaurada. No la original, porque la original ya está inaccesible, sino la restaurada.

Por lo tanto, si por algún motivo te interesa poder seguir accediendo a la Base de Datos original entonces el ciclo backup/restore que la reemplazará deberías hacerlo bastante antes de llegar al límite de 2.147.483.647 transacciones, por ejemplo al llegar a las 2.147.000.000 de transacciones podrías hacer un ciclo backup/restore y desde ese momento empezar a usar la Base de Datos restaurada, no la original. A la original podrás acceder un máximo de 483.647 veces más, cuando sea estrictamente necesario.

Artículos relacionados:

La Next Transaction después de un ciclo backup/restore

El índice del blog Firebird21

El foro del blog Firebird21