En Firebird es extremadamente importante tener un buen manejo de las transacciones porque eso nos asegura que nuestra Base de Datos se encuentre en perfecto estado de salud.

Cuando no es así, se degrada el rendimiento porque el tamaño de la Base de Datos es mayor del que debería ser ya que está teniendo mucha basura dentro de ella y eso afecta a la velocidad con la cual se realizan las operaciones (SELECT, INSERT, UPDATE, DELETE, FETCH).

En este artículo habíamos visto el significado de los identificadores de las transacciones:

https://firebird21.wordpress.com/2013/09/08/entendiendo-los-identificadores-de-las-transacciones/

Podemos ver los valores actuales de esos identificadores usando el programa GSTAT y la opción -h, ejemplo:

C:\Archivos de Programa\Firebird\Firebird_2_5\bin>GSTAT -h MiBaseDatos

TRANSA01

Captura 1. Si haces clic en la imagen la verás más grande

En la Captura 1 tenemos un ejemplo de una Base de Datos muy bien administrada porque la diferencia entre los valores de Oldest transaction Oldest active Oldest snapshot es de 1 y la diferencia entre Oldest activeNext transaction también es de 1. Esa es la menor diferencia que podemos tener y nos indica que las transacciones de esta Base de Datos se encuentran en perfecto estado. Pero esa diferencia de 1 solamente podemos tenerla cuando nadie está usando la Base de Datos ya que mientras está en uso la diferencia casi siempre será mayor que 1 pero nunca debería ser más que 10 multiplicado por el número de usuarios. Es decir que si hay 16 personas usando la Base de Datos una diferencia mayor que 160 implicaría que algunas transacciones continúan activas cuando no deberían estarlo.

Aquí hay otro ejemplo:

TRANSA02

Captura 2. Si haces clic en la imagen la verás más grande

En la Captura 2 descubrimos que hay una diferencia significativa entre la OAT (Oldest Active Transaction) y Next transaction y nadie está usando la Base de Datos en este momento ¿Qué significa eso? que la transacción 3999 no finalizó ni con un COMMIT ni con un ROLLBACK, es por lo tanto una transacción “colgada” y debe ser corregida porque de no hacerlo se irá acumulando basura. En Oldest snapshot tenemos el número de la transacción más antigua cuya basura no puede ser recolectada automáticamente. O sea que toda la basura que dejaron las transacciones 3999 a 4196 no puede ser recolectada. Evidentemente cuanto mayor sea la diferencia entre Next transaction y Oldest snapshot mayor será el problema que tendremos con la basura.

La solución aquí es ejecutar un sweep manualmente, así:

GFIX -sweep -user SYSDBA -password masterkey MiBaseDatos

Al finalizar la ejecución de ese programa volvemos a verificar las estadísticas de la Base de Datos y esto es lo que obtenemos:

TRANSA03

Captura 3. Si haces clic en la imagen la verás más grande

¡¡¡Perfecto!!! Ahora sí la Base de Datos está sin basura y con los valores de los identificadores de las transacciones correctos.

Ejemplo de transacciones mal administradas

El motivo de escribir este artículo es que ví en Internet un mensaje de alguien pidiendo ayuda porque el sweep no le funcionaba. Los valores de los identificadores de sus transacciones eran los siguientes:

Oldest transaction  371932
Oldest active      1906983
Oldest snapshot    1906983
Next transaction   2696106

¿Qué podemos deducir mirando esos números?

  1. La transacción 371932 no finalizó con un COMMIT
  2. La transacción 1906983 no finalizó ni con un COMMIT ni con un ROLLBACK
  3. No se puede recolectar la basura que dejaron las transacciones 1906983 a 2696105
  4. Como la diferencia entre la Oldest active y la Next transaction es muy grande entonces es seguro que la aplicación que creó la transacción Oldest active (Contabilidad, Facturación, Ventas, Sueldos, etc.) ya se olvidó totalmente de ella y jamás le hará ni un COMMIT ni un ROLLBACK. Eso implica que hay que revisar la aplicación para descubrir por qué dejó una transacción activa y corregir ese problema (todas las transacciones deberían finalizar con un COMMIT o con un ROLLBACK, aún las que solamente hacen un SELECT)
  5. El sweep (barrido) solamente afectará a las transacciones del 1 al 371931. Toda la basura dejada por las transacciones 371932 a 2696105 no podrá ser eliminada ¿por qué no? porque si se la eliminara entonces la transacción 1906983 ya no tendría una visión estable de la Base de Datos
  6. Por lo tanto, la solución es buscar a la transacción 371932 y eliminarla. Y luego volver a intentar el sweep.
  7. Si el problema continúa entonces repetir el paso 6. para las siguientes Oldest transaction cuyos valores sean menores que Oldest active.

NOTA: Como la transacción 371932 no finalizó con un COMMIT entonces eliminarla no afectará al contenido de las tablas que tengamos en nuestra Base de Datos ya que el contenido de las tablas solamente es afectado por las transacciones que finalizan con un COMMIT.

Conclusión:

Periódicamente (una vez al día, una vez a la semana, una vez al mes, dependiendo de la cantidad de transacciones que tiene tu Base de Datos) deberías verificarla para comprobar que se encuentra en perfecto estado, de no ser así deberías tomar las medidas adecuadas para que lo esté.

Artículos relacionados:

Entendiendo los identificadores de las transacciones

Entendiendo sweep y garbage collection

El índice del blog Firebird21

Anuncios