Conectando a una Base de Datos desde dos servidores

2 comentarios

Si tu intención es corromper, destruir, destrozar internamente, a una Base de Datos del Firebird, esta es una de las formas más seguras de conseguirlo.

Así que si tu intención es mantener a la Base de Datos en muy buen estado de conservación, jamás hagas algo así.

Veamos un poco más detalladamente lo que sucedería si intentas conectarte a una misma Base de Datos desde dos (o más) servidores de Firebird al mismo tiempo.

Como recordarás, Firebird tiene tres arquitecturas: Classic, SuperClassic, SuperServer.

Classic y SuperClassic son ejecutados a través de un programa que se llama FB_INET_SERVER.EXE y realizan los bloqueos correctos usando el proceso FB_LOCK_MGR.

Entonces, aunque cada conexión usando Classic y SuperClassic se hace mediante servidores distintos (cada instancia ejecuta a un FB_INET_SERVER.EXE), el proceso FB_LOCK_MGR se encarga de gestionar esas conexiones asegurándose de que la Base de Datos no se corrompa.

SuperServer por otro lado es ejecutado a través de un programa que se llama FBSERVER.EXE, el cual requiere acceso exclusivo a la Base de Datos así que resulta imposible que otro Servidor pueda acceder a una Base de Datos a la cual alguien ya se conectó usando SuperServer. Y también que si alguien ya se conectó a una Base de Datos (usando Classic, SuperClassic, o SuperServer)  alguien más pueda conectarse a ella usando otro Servidor SuperServer.

Entonces la situación es la siguiente:

  • Si alguien se conectó a una Base de Datos usando SuperServer, nadie más podrá conectarse a esa Base de Datos usando otro Servidor (sea Classic, SuperClassic, o SuperServer dicho Servidor).
  • Si alguien se conectó a una Base de Datos (usando Classic, SuperClassic, o SuperServer), conectarse a esa Base de Datos usando otro Servidor, que sea SuperServer, será imposible.
  • Si alguien se conectó a una Base de Datos usando Classic o SuperClassic conectarse a esa Base de Datos usando otro Servidor que sea Classic o SuperClassic, sí es posible … pero corromperá a la Base de Datos.

El último punto es el peligroso.

¿Y por qué se corromperá la Base de Datos?

Hay dos cosas que pueden salir mal, muy mal.

Primero. Los índices estarán corruptos. Si desde el Servidor 1 se están insertando filas a una tabla y desde el Servidor 2 también se están insertando filas a esa misma tabla, cada Servidor actualizará los índices de la tabla, al mismo tiempo, y eso ocasionará un desbarajuste mayúsculo. Esto es solucionable. Cuando ningún Servidor está insertando ni borrando ni modificando filas de esa tabla se reconstruyen los índices y asunto solucionado. Pero si se trata de una tabla que tiene muchos movimientos tantas reconstrucciones de índices afectarán gravemente al rendimiento y además mientras tanto las consultas mostrarán datos incorrectos y los procesos también realizarán actualizaciones incorrectas.

Segundo. Un Servidor sobre-escribe las páginas del otro Servidor. Esto es gravísimo porque causará corrupción en el 100% de los casos. Como recordarás, Firebird guarda todo, absolutamente todo lo que se hace en una Base de Datos en bloques de bytes llamados páginas. Si hay dos servidores accediendo a una misma Base de Datos, no se tendrá una buena administración de esas páginas porque cada Servidor llamará a un proceso FB_LOCK_MGR diferente. Y cada uno de esos procesos guarda el estado actual de las páginas de la Base de Datos en una porción de memoria RAM a la cual tiene acceso exclusivo.Por ejemplo: el Servidor 1 necesita una nueva página para datos de la tabla VENTAS, ve que la página número 123456 está libre y marca esa página para contener datos de la tabla VENTAS. Todo bien hasta ahí. Pero el Servidor 2 también necesita una nueva página, en este caso para guardar los índices de la tabla PRODUCTOS, ve que la página número 123456 está libre y marca a esa página para contener los índices de la tabla PRODUCTOS. ¿Consecuencia? Que las ventas que se guardaron en la página 123456 se perdieron totalmente. Y que los índices que correspondían a esas ventas están huérfanos. Los productos no tendrán problemas, pero las ventas se corrompieron. Por supuesto que más adelante la situación puede ser a la inversa y los datos corruptos son los correspondientes a la tabla de PRODUCTOS. El problema por lo tanto es que si dos o más servidores están conectados a una misma Base de Datos la correcta administración de las páginas de esa Base de Datos será imposible, y la corrupción no tardará en llegar.

Conclusión:

Conectarse a una misma Base de Datos usando dos servidores, siendo al menos uno de esos servidores SuperServer, es imposible.

Si los servidores son Classic o SuperClassic la conexión sí es posible, pero con toda seguridad causará corrupción a la Base de Datos.

¿Por qué se corromperá la Base de Datos?

Un problema se tendrá con los índices, y aunque esto es solucionable será muy molesto porque se tendrá que reconstruirlos constantemente y eso hará que todas las operaciones se vuelvan muy lentas, o que las consultas muestren datos inconsistentes.

Pero el problema realmente grave se tendrá con las páginas de datos que fueron escritas por uno de los servidores y sobre-escritas por el otro Servidor. Esto ocurrirá porque cada Servidor guarda en una porción de la memoria RAM  (que es de su uso exclusivo) el estado de las páginas de la Base de Datos. Por lo tanto, lo que hace un Servidor el otro Servidor no lo sabe, lo ignora completamente.

Y claro, un Servidor marca una página para que guarde algo, y el otro Servidor marca a esa misma página para que guarde otra cosa. ¿Consecuencia? Corrupción asegurada, 100% asegurada.

Artículos relacionados:

Entendiendo las páginas de la Base de Datos

Eligiendo el tamaño adecuado de las páginas de la Base de Datos

El índice del blog Firebird21

El foro del blog Firebird21

 

 

 

Detectando y eliminando filas duplicadas

Deja un comentario

En una Base de Datos bien diseñada nunca deberíamos tener filas duplicadas pero … a veces tal cosa ocurre. Quizás porque heredamos una Base de Datos de alguien que no sabía mucho como se hace un buen diseño.

Entonces ahora tenemos 3 tareas:

  1. Detectar si hay filas duplicadas
  2. Averiguar cuales son las filas duplicadas
  3. Eliminar las filas duplicadas

Aunque se diga “duplicadas”, en realidad debe entenderse como filas que deberían ser únicas y no son únicas, eso incluye: duplicadas, triplicadas, cuadruplicadas, etc.

Para entender mejor, mostraremos un ejemplo. Tenemos una tabla llamada PROVEEDORES. En esa tabla la columna PRO_RUCXXX debería ser única. El RUC es un número que en algunos países se utiliza para identificar a los contribuyentes fiscales.

Primer paso. Detectando si hay filas duplicadas.

Para saber si en la tabla de PROVEEDORES tenemos RUC duplicados, escribimos:

Listado 1.

SELECT
   PRO_RUCXXX,
   COUNT(*) AS CANTIDAD_FILAS
FROM
   PROVEEDORES
GROUP BY
   PRO_RUCXXX
HAVING
   COUNT(*) >= 2

ELIMINANDO1

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

Al ejecutar el Listado 1. obtenemos lo que vemos en la Captura 1. y así descubrimos que los datos de varios proveedores han sido escritos, incorrectamente desde luego, más de una vez.

Ok, ya sabemos que hay proveedores con datos duplicados, ahora nuestra siguiente tarea es averiguar los datos de esos proveedores.

Segundo paso. Averiguar cuales son las filas duplicadas.

El Listado 1. no nos dice cuales son los identificadores de los proveedores cuyos RUC están duplicados, y eso es algo que nos interesa conocer. Así que escribimos:

Listado 2.

SELECT
   T1.PRO_IDENTI,
   T1.PRO_RUCXXX
FROM
   PROVEEDORES T1
WHERE
   EXISTS (SELECT
              T2.PRO_IDENTI
           FROM
              PROVEEDORES T2
           WHERE
              T1.PRO_RUCXXX = T2.PRO_RUCXXX AND
              T1.PRO_IDENTI > T2.PRO_IDENTI)
ORDER BY
   T1.PRO_RUCXXX

ELIMINANDO2

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

Ok, ya sabemos cuales son los identificadores y los RUC de los proveedores cuyos datos están duplicados (y también hay un caso de triplicados).

Ahora, nuestra última tarea es eliminar a esas filas que están sobrando.

Tercer paso. Eliminando las filas duplicadas.

Esto ya es muy fácil, es simplemente reemplazar el SELECT del Listado 2. por un DELETE, nos quedaría así:

Listado 3.

DELETE FROM
   PROVEEDORES T1
WHERE
   EXISTS (SELECT
              T2.PRO_IDENTI
           FROM
              PROVEEDORES T2
           WHERE
              T1.PRO_RUCXXX = T2.PRO_RUCXXX AND
              T1.PRO_IDENTI > T2.PRO_IDENTI)

Si al ejecutar el Listado 3. obtenemos un mensaje similar al siguiente: ‘Violation of FOREIGN KEY constraint “FK_COMPRASCAB” on table “COMPRASCAB”‘, eso significa que el Identificador de uno (o más de uno) de los proveedores que quisimos borrar fue usado en la restricción Foreign Key de otra tabla (en este ejemplo, la tabla se llama COMPRASCAB).

¿Solución?

Actualizar el Identificador de proveedor de la tabla que tiene la restricción Foreign Key (en este caso, COMPRASCAB), poniendo un solo Identificador. O sea que si en la fila cuyo Identificador es 81 el RUC es 1421744-9 y en la fila cuyo Identificador es 162 el RUC también es 1421744-9, debemos cambiar el Identificador 162 por el Identificador 81 en todas las filas de la tabla COMPRASCAB cuyo Identificador sea 162.

O sea, en la tabla COMPRASCAB, todos los Identificadores de proveedores 162 se cambiarán por 81.

¿Y cómo podemos ver los Identificadores de todos los proveedores que tiene RUC repetidos?

Con un SELECT similar al siguiente:

Listado 4.

SELECT
   T1.PRO_IDENTI,
   T1.PRO_RUCXXX
FROM
   PROVEEDORES T1
WHERE
   EXISTS (SELECT
              T2.PRO_RUCXXX
           FROM
              PROVEEDORES T2
           WHERE
              T1.PRO_RUCXXX = T2.PRO_RUCXXX
           GROUP BY
              T2.PRO_RUCXXX
           HAVING
              COUNT(*) >= 2)
ORDER BY
   T1.PRO_RUCXXX

ELIMINANDO3

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

En la Captura 3. vemos el resultado de ejecutar el Listado 4. y así podremos saber cuales son los Identificadores de los proveedores cuyos RUC están repetidos.

Conclusión:

En nuestras tablas no debemos tener filas duplicadas pero a veces tal cosa ocurre. En casos así nuestras tareas serán detectar si hay filas duplicadas, encontrar cuales son las filas duplicadas, y eliminar las filas duplicadas.

Algo que está en la Base de Datos pero que no debería estar se llama basura, y las filas duplicadas son un ejemplo de basura.

Artículos relacionados:

Obteniendo la primera fila de cada grupo

El índice del blog Firebird21

El foro del blog Firebird21

 

Trabajando con grandes bases de datos

3 comentarios

Los problemas con los cuales nos encontramos al trabajar con bases de datos grandes son distintos a los problemas que tienen las bases de datos pequeñas.

Como las empresas constantemente están almacenando más y más datos las tablas van creciendo de tamaño diariamente, quizás minuto a minuto. Llega un momento en que la Base de Datos ya puede considerarse “grande”.

¿Cuándo una Base de Datos es grande?

Como muchas otras cosas en Informática, ésta también depende del punto de vista. Para alguien podría ser grande y para otros pequeña, aunque en general se considera “grande” a las bases de datos que alcanzan o superan un tamaño de 10 Gigabytes. En este blog se considera que:

  • Pequeña. Es una Base de Datos con tamaño menor a 1 Gb
  • Mediana. Es una Base de Datos cuyo tamaño está entre 1 Gb y 10 Gb
  • Grande. Es una Base de Datos cuyo tamaño es mayor que 10 Gb

Normalmente, si no se almacena multimedia (archivos gráficos, de sonido, de vídeo, etc.) las bases de datos van creciendo a un ritmo bastante parejo y predecible, por ejemplo podríamos tener una que crece alrededor de 1 Megabyte por día. Desde luego que algunos días crece más y algunos días crece menos, pero siempre está por ahí cerca.

Problemas típicos con las bases de datos pequeñas

  • Consultas lentas
  • Stored procedures o triggers lentos

Soluciones típicas a esos problemas

  • Optimizar las instrucciones SQL.
  • Realizar un ciclo backup/restore con el programa GBAK

El optimizar las instrucciones SQL (principalmente las cuatro principales: INSERT, UPDATE, DELETE, SELECT) conduce a una notoria mejoría en la velocidad. Muy relacionado con esto se encuentra el correcto manejo de las transacciones. Ante alguna corrupción restaurar el backup realizado con GBAK suele ser suficiente.

Problemas típicos con las bases de datos grandes

  • No se sabe donde está el problema
  • No se sabe por qué sucede
  • Realizar un ciclo backup/restore puede ser una gran pérdida de tiempo, porque la restauración puede demorarse un día o más, y no asegura que se haya solucionado el problema

Tareas administrativas diarias en las bases de datos grandes

Si ocurre un problema, puede demorarse mucho la solución así que lo más inteligente es evitar que ocurra. Para ello:

  1. Debe realizarse un backup con GBAK todos los días
  2. Debe verificarse el rendimiento de todas las transacciones
  3. Debe verificarse que todas las instrucciones SQL estén optimizadas
  4. Debe verificarse cada índice y la estadística de cada índice
  5. Debe verificarse que la estructura de la Base de Datos sea la más conveniente
  6. Debe verificarse el archivo FIREBIRD.LOG varias veces por día

Aunque realizar un ciclo backup/restore no nos asegura que solucionaremos todos los problemas, tener una Base de Datos grande sin backups actualizados es un suicidio. En las transacciones lo más importante es que ninguna demore mucho en completarse (“mucho” es relativo, pero en general si tarda más de un minuto entonces está tardando una eternidad). Las instrucciones SQL no optimizadas hacen perder tiempo, algo que no se puede permitir en estas circunstancias. Y no debemos olvidar que una instrucción SQL que hoy está optimizada y funciona perfectamente podría dejar de estarlo dentro de unos meses cuando la Base de Datos haya aumentado mucho de tamaño. Por eso la verificación debe hacerse diariamente.

El archivo FIREBIRD.LOG es el mejor lugar para verificar que todo esté correcto, si hay algún problema casi siempre aparecerá en ese archivo.

¿Cómo realizar el ciclo backup/restore?

Es bastante frecuente, aunque erróneo, hacerlo de esta manera:

Base de Datos —> Backup con el mismo nombre anterior

Por ejemplo, la Base de Datos se llama CONTA.FDB y el archivo de backup siempre se llama CONTA.FBK, ¿cuál es el problema potencial? Que si la Base de Datos está corrupta entonces el nuevo backup no servirá y el anterior no podrá ser utilizado porque fue sobre-escrito.

Lo correcto, por lo tanto, es hacer el backup de esta manera:

Base de Datos —> Backup con un nombre distinto al anterior

Esto evidentemente implica que tendremos varios archivos de backup, pero es preferible que sobren y no que falten.

El archivo delta

Cuando se ejecuta el programa GBAK para realizar un backup, éste hace el backup de todo el contenido que tiene en ese momento la Base de Datos. Es como si le tomara una fotografía. Nada que se realice con posterioridad se guardará en el backup ni en la Base de Datos, sólo lo que existía en el momento de iniciarse GBAK. Pero ¿y qué pasa con los datos que los usuarios continúan insertando, actualizando o borrando? Que no se guardan en la Base de Datos original sino en un archivo temporario llamado delta. Cuando GBAK finaliza, entonces todo el contenido del archivo delta se copia dentro de la Base de Datos.

Cuando hacemos backup de bases de datos pequeñas no vale la pena preocuparse por ese archivo delta pero cuando es una Base de Datos grande sí, porque no podemos permitirnos que esté corrupto. Un motivo podría ser que no haya suficiente espacio en el disco duro para el archivo delta.

La restauración

Aquí, es obligatorio que al finalizar un backup se realice un restore (en otro disco duro y preferiblemente en otra computadora) para asegurarnos de que se encuentre en perfectas condiciones y pueda ser utilizado en caso de necesidad.

Nada hay peor que creer que se tiene un backup actualizado pero eso no es cierto porque el backup se encuentra inservible. No ocurre frecuentemente, pero a veces ocurre, y no se puede tomar ese riesgo.

Los índices

Los índices en Firebird se utilizan en las búsquedas y en los filtros (cláusula WHERE) y cuando deseamos que los resultados aparezcan en un cierto orden (cláusula ORDER BY)

Para saber si un índice es el adecuado, es necesario, y se encuentra en buena salud, debemos verificar sus estadísticas. En Firebird los índices pueden degradarse y no debemos permitir que tal cosa ocurra.

Acciones a tomar si se descubre un problema

Estas son recomendaciones que a veces podrían no aplicarse, dependen de cada caso, pero servirán de guía:

  1. Una transacción está demorando mucho. Detectar cual es la transacción, cual es el programa culpable, y desconectar al usuario
  2. Una consulta está demorando mucho. Verificar cual es la consulta, mirar su PLAN y si es necesario crear un nuevo índice

Programas que se pueden utilizar cuando se trabaja con grandes bases de datos

Aunque detectar los problemas y solucionarlos podría hacerse manualmente, eso requerirá que la persona encargada conozca mucho del tema y que tenga suficiente tiempo y ganas para dedicarle a esa tarea. Para estos casos se justifica adquirir software que ayude en la detección y corrección. Los recomendados son:

  • FBDataGuard. Se ejecuta en la misma computadora donde se encuentra la Base de Datos. Su principal tarea es prevenir que se corrompa. Monitorea el rendimiento, realiza el backup en la forma correcta, obtiene estadísticas, y si descubre algún problema entonces envía un e-mail describiéndolo
  • FBScanner. Verifica cada instrucción SQL que el Cliente le envía al Servidor, puede realizar un análisis detallado de cada consulta, PLAN, transacción y conexión, de esta manera sirve para detectar los “cuellos de botella”, las transacciones que se demoran mucho, los usuarios que se desconectan de mala manera, y monitorea lo que un usuario o una aplicación están realizando.
  • IBTM. Monitorea y analiza transacciones dinámicas. Obtiene los valores de OIT, OAT, OST, NT y visualiza como se van moviendo. Detecta transacciones que se demoran mucho, los momentos en que muchas transacciones se están ejecutando, los momentos en que ocurre el sweep, la basura dejada por los ROLLBACKs.
  • IBAnalyst. Analiza las estadísticas de la Base de Datos e identifica posibles problemas que causan un bajo rendimiento: transacciones que demoran mucho, cantidad de versiones de los registros, registros que han sido borrados pero aún permanecen en la Base de Datos y por lo tanto demoran la lectura, promedio de transacciones por día, conexiones perdidas, índices no usados, índices con muchos valores repetidos, etc.
  • FBMonLogger. Detecta consultas lentas, transacciones que tienen un aislamiento incorrecto, basura que debe ser recolectada, uso de la memoria, etc.
  • Sinática. Monitorea a la Base de Datos en tiempo real, ayudando a detectar los procesos que consumen muchos recursos o que producen “cuellos de botella”, además de las transacciones que demoran mucho en finalizar.

Conclusión:

Aunque realizar las tareas administrativas de backup, verificación de las estadísticas de los índices, revisar el archivo FIREBIRD.LOG, etc. deberían hacerse regularmente con cualquier Base de Datos, cuando éstas son de gran tamaño esas tareas ya son una obligación imprescindible porque no se puede correr el riesgo de que se corrompa o de que funcione muy lentamente, muchas veces tales bases de datos deben funcionar 365/24/7 (o sea, los 365 días del año, durante las 24 horas, de cada uno de los 7 días de la semana) y cualquier demora o detención puede ser muy grave.

En estos casos, suele ser recomendable contratar a una persona cuya función sea la de Administrador de la Base de Datos y proveerle de las herramientas informáticas adecuadas para que pueda realizar efectivamente su labor.

Artículos relacionados:

El índice del blog Firebird

El foro del blog Firebird21

Artículos

Precauciones al usar Firebird Embedded

4 comentarios

Como seguramente ya sabes, puedes usar Firebird con 4 arquitecturas diferentes:

  • Classic
  • SuperClassic
  • SuperServer
  • Embedded

Las tres primeras normalmente tienen al Servidor en una computadora y al Cliente en cada una de las computadoras que necesitan acceder a la/s base/s de dato/s. Una de esas tres primeras arquitecturas debemos usar cuando queremos que varios usuarios estén conectados al mismo tiempo a la misma Base de Datos, este es el caso más frecuente cuando usamos Firebird. Colocamos a las bases de datos en una carpeta no compartida que se encuentra en la misma computadora donde se encuentra el Servidor y éste es quien se encarga de acceder a esas bases de datos cuando los Clientes se lo soliciten. Eso está muy bien y funciona perfectamente.

La arquitectura Embedded en cambio la usaríamos cuando siempre será una sola persona quien se conectará a la Base de Datos, como sería en el caso de una aplicación monousuario.

¿Y qué ocurrirá si ponemos a la Base de Datos en una carpeta compartida y permitimos que accedan a ella desde varias computadoras de la red usando Embedded?

Que ocurrirá una catástrofe y se destrozará y volverá inservible a la Base de Datos.

¿Por qué eso?

 Porque Embedded puede manejar varias conexiones, pero con la condición de que todas esas conexiones correspondan a un mismo proceso. Siendo así, él administrará los cambios a las páginas correctamente, evitando que una conexión sobre-escriba los cambios hechos por otra conexión.

Sin embargo, si desde varias computadoras se está accediendo mediante Embedded a una Base de Datos que se encuentra en una carpeta compartida se terminará con esa Base de Datos destruida.

 Eso es debido a que cada Embedded cree que tiene acceso exclusivo a la Base de Datos y realiza en ella los cambios que necesita, pero otros Embedded pueden estar realizando otros cambios en las mismas páginas.

Ejemplo:

Un proceso Embedded necesita una nueva página para guardar en ella los datos de la tabla PRODUCTOS, esa nueva página tiene el número 5.000

Otro proceso Embedded necesita una nueva página para guardar en ella los índices de la tabla VENTAS, esa nueva página también tiene el número 5.000

No olvides que cada proceso cree que tiene acceso exclusivo a la Base de Datos y por lo tanto desconoce lo que otros procesos le están haciendo a esa Base de Datos. Un Embedded no tiene forma de saber que otro Embedded está accediendo a la misma Base de Datos.

En algún momento el problema se vuelve catastrófico, cuando una página TIP se convierte en una página de cualquier otra cosa y se perdió el acceso a todos los datos.

Desastre total.

Conclusión:

Si más de un usuario accederá a una Base de Datos de Firebird al mismo tiempo, entonces debemos usar una arquitectura Classic, SuperClassic, o SuperServer para ello.

Podemos usar Embedded cuando estamos 100% seguros de que solamente un usuario se conectará y jamás, por ningún motivo, se conectará más de un usuario.

Si ponemos a una Base de Datos en una carpeta compartida de la red y permitimos que accedan a ella usando Embedded es seguro que en algún momento esa Base de Datos se volverá totalmente inservible.

Artículos relacionados:

Entendiendo a las páginas de la Base de Datos

El índice del blog Firebird21

El foro del blog Firebird21

 

 

Usando Firebird durante 24/7/365

5 comentarios

Algunas aplicaciones requieren acceso a las bases de datos durante 24/7/365, o sea durante las 24 horas del día, los 7 días de la semana y los 365 días del año. En otras palabras: sin interrupción, por ningún motivo.

Algunos ejemplos típicos son:

  • Sanatorios, hospitales, centros de salud
  • Farmacias que trabajan las 24 horas
  • Estaciones de servicio (expendio de combustibles)
  • Policía
  • Fuerzas Armadas
  • etc.

Una aplicación desarrollada para ser utilizada por ellos tiene la obligación de poder funcionar sin interrupción en cualquier momento del día. No le puedes decir al Director de un hospital que entre las 22:00 y las 23:00 no pueden registrarse los datos de los pacientes porque hay que hacerle un mantenimiento a la Base de Datos. Ni decirle a un General que si mañana el país es atacado por el enemigo entre las 02:00 y las 03:00 entonces no podrá usar la Base de Datos porque ya tiene mucha basura y que hiciste un proceso para que elimine esa basura pero requieres que nadie esté conectado a la Base de Datos.

¿Y cuál es el problema?

El problema radica en que a las bases de datos de Firebird debe hacérsele una tarea de mantenimiento llamada sweep de vez en cuando. El sweep (barrido, en castellano) tiene como finalidad eliminar a todas las versiones inútiles de las filas que fueron modificadas o borradas. Cada vez que una fila es modificada o borrada se crea una versión de esa fila llamada delta. La parte positiva de esto es que puede realizarse un ROLLBACK y dejar a la fila como se encontraba anteriormente si el usuario cambió de idea. La parte negativa es que se va acumulando basura y todas las operaciones se van volviendo más lentas y por lo tanto esa basura debe ser eliminada alguna vez.

 Y el sweep puede demorar mucho tiempo.

¿Cuándo se inicia el sweep?

El sweep puede iniciarse automáticamente (que es su valor por defecto) cuando la diferencia entre la OST (Oldest Snapshot Transaction) y la OAT (Oldest Active Transaction) es mayor que el intervalo predefinido del sweep. Ese intervalo es de 20.000 por defecto pero puede modificarse.

Si el intervalo del sweep es de 0, entonces el sweep nunca se iniciará automáticamente. Eso implica que hay que iniciarlo manualmente. Para ello se usa el programa GFIX con la opción –sweep. En este caso lo recomendable es que nadie esté usando la Base de Datos mientras se realiza el sweep.

 ¿Qué ocurre cuándo se inicia el sweep?

Que la transacción que hizo iniciar al sweep no empezará hasta que el sweep finalice. Supongamos que el intervalo del sweep es de 20.000, entonces el desafortunado usuario que quiso iniciar una transacción cuando OST – OAT fue de 20.001 tendrá que esperar hasta que finalice el sweep antes de que su transacción pueda empezar. A quienes iniciaron sus transacciones antes que él no les afectará, pero a él sí. Y si justo es un General de muy malas pulgas, entonces…

 ¿Se puede evitar que se inicie el sweep sin perjudicar el rendimiento de la Base de Datos?

Sí.

La buena noticia es que si las aplicaciones que usan la Base de Datos están correctamente diseñadas entonces nunca será necesario realizar el sweep.

La basura que se encuentra dentro de una Base de Datos puede deberse a los siguientes motivos:

  • Una operación de UPDATE que finalizó con un COMMIT
  • Una operación de DELETE que finalizó con un COMMIT
  • Una operación de UPDATE que finalizó con un ROLLBACK
  • Una operación de DELETE que finalizó con un ROLLBACK

La basura dejada por las transacciones que finalizaron con un COMMIT es recolectada (garbage collection) automáticamente cuando se hace un SELECT a esas filas. Por lo tanto, para eliminar toda la basura de una tabla que fue dejada por los COMMIT se puede escribir un simple comando: SELECT * FROM MiTabla y listo: esa tabla ya no tendrá basura dejada por los COMMIT.

La basura dejada por el ROLLBACK sin embargo, solamente puede ser eliminada con un sweep.

Por lo tanto la solución es muy simple y muy sencilla: No usar ROLLBACK.

¿Y cómo se puede evitar usar ROLLBACK?

Hay varias alternativas posibles, una posible solución sería esta:

  • Haces un SELECT a la fila que te interesa, por supuesto finalizando ese SELECT con un COMMIT. El resultado de ese SELECT lo guardas en una tabla temporal que no es de Firebird, por ejemplo en una tabla .DBF
  • Le muestras la fila de la tabla .DBF al usuario
  • Le permites que cambie los campos o que borre la fila
  • Si decide Guardar los cambios, entonces haces un UPDATE a la tabla de Firebird con los valores que se ven en la pantalla y luego el COMMIT correspondiente
  • Si decide Cancelar los cambios, entonces allí termina todo, no tocas la tabla de Firebird para nada

Como ves, en estos casos se trabaja un poco más pero te aseguras que todas las transacciones terminen con un COMMIT.

Recolectando la basura

Adicionalmente, en tu aplicación deberías tener un proceso que se encargue de hacer un SELECT * a todas las tablas de tu Base de Datos. Cuando el usuario ejecuta ese proceso entonces se hace un SELECT * FROM MiTabla1, SELECT * FROM MiTabla2, SELECT * FROM MiTabla3, etc.

Recordatorio:

La técnica mostrada en este artículo es necesaria solamente para las bases de datos que deben estar activas durante 24/7/365. En los demás casos se puede seguir el procedimiento normal de hacer el sweep automáticamente o manualmente.

Conclusión:

Las bases de datos de Firebird pueden perfectamente ser usadas en entornos que las requieren abiertas durante las 24 horas, los 7 días de la semana y los 365 días del año. Lo que debemos tener en cuenta en esos casos es que deberíamos evitar el sweep porque el sweep puede demorar mucho tiempo en bases de datos muy grandes. La forma de evitar el sweep es nunca terminar las transacciones con ROLLBACK porque las transacciones que terminan con ROLLBACK dejan basura que solamente puede ser eliminada con un sweep, en cambio la basura dejada por las transacciones que terminan con un COMMIT puede ser eliminada con un comando SELECT * FROM MiTabla.

 Entonces, el problema es causado por la forma en que Firebird actúa cuando se hace un UPDATE o un DELETE que finalizaron con un ROLLBACK pero puede ser solucionado si la aplicación finaliza todas las transacciones con un COMMIT.

Artículos relacionados:

La arquitectura MGA

Entendiendo a las transacciones

Entendiendo a los identificadores de las transacciones

Entendiendo sweep y garbage collection

El índice del blog Firebird21

El foro del blog Firebird21

 

Usando Firebird con WiFi

2 comentarios

En esta época es muy común que haya conexiones WiFi en todas partes, tanto en los hogares como  en las oficinas e inclusive en lugares públicos. Entonces la pregunta es: ¿qué tan eficiente es usar Firebird con WiFi?

Primero, hay que decir que es perfectamente posible pero … pueden ocurrir problemas. Veamos:

Pérdidas de señal

En una red WiFi casi siempre en un momento o en otro ocurren pérdidas de señales, si haces una búsqueda con Google verás que hay millones de personas quejándose de eso. La culpa de la pérdida de señal puede ser del hardware o del software. Pero vayamos a lo nuestro:

El Servidor del Firebird no sabe si te has conectado a la Base de Datos por medio de una red cableada o por medio de WiFi. Eso implica que lo importante es la calidad de tu red, no de si es cableada o WiFi.

Si la culpa de la pérdida de señal es del hardware, entonces hay que reemplazarlo. No pretendas conectar a ochopotocientas computadoras con un router WiFi barato, de esos que cuestan casi lo mismo que una docena de caramelos. Si la conexión será por WiFi entonces el router debe ser de una marca bien conocida, de muy buena calidad. Esto se lo debes aclarar muy bien a tu cliente, y por escrito, para que luego no te echen la culpa de la lentitud o del tiempo perdido. Desde luego que esto se aplica a todo tipo de redes, sean cableadas o WiFi: si tu cliente quiere buena velocidad entonces debe invertir en hardware de buena calidad, no puedes garantizar ni velocidad ni confiabilidad si no es así. Aunque en una red cableada con hardware de mala calidad podrías obtener un resultado aceptable con redes WiFi nunca es así: hardware malo implica rendimientos miserables con bases de datos.

Si la culpa de la pérdida de señal es del software entonces eso significa que no está bien configurado. Y aquí hay varios puntos que tener en cuenta:

  1. El Windows puede desconectarse del router para ahorrar energía. Puedes verificarlo entrando en Panel de Control | Administrador de dispositivos | Adaptadores de red | Nombre_de_tu_router | Propiedades | Administración de energía. Si está marcada la opción “Permitir que el equipo apague este dispositivo para ahorrar energía”, quítale la marca.
  2. En el archivo FIREBIRD.CONF que se encuentra en la carpeta donde instalaste el Firebird hay una entrada llamada DummyPacketInterval que sirve para indicarle al Servidor del Firebird cuantos segundos debe esperar antes de enviarle un paquete vacío de reconocimiento al Cliente. ¿Qué significa esto? Que si el Cliente no está enviando solicitudes al Servidor (un comando INSERT, UPDATE, DELETE, SELECT, etc., por ejemplo) el Servidor no puede saber si el Cliente continúa conectado o si se ha desconectado. La forma de verificar que continúa conectado es enviándole un paquete vacío que solamente sirve para reconocimiento. Si el Cliente le envía una respuesta al Servidor entonces el Servidor sabe que el Cliente continúa conectado. Si el Cliente no le envía una respuesta entonces evidentemente se murió la conexión. La entrada DummyPacketInterval sirve justamente para eso: para decirle al Servidor cada cuantos segundos debe verificar que el Cliente está conectado.
  3. En el punto 1. hemos visto como pedirle al Servidor que verifique la conexión pero … ¿y si queremos que sea el Cliente quien la verifique? Esto siempre es importante, antes de enviarle un comando (INSERT, UPDATE, DELETE, SELECT, EXECUTE PROCEDURE, etc.) al Servidor queremos verificar que hay una conexión activa. La forma más sencilla y rápida de conseguirlo es pidiéndole al Servidor que nos devuelva algún dato, por ejemplo la fecha de hoy. Para ello le podemos enviar un comando como: SELECT CURRENT_DATE FROM RDB$DATABASE y si como resultado obtenemos una fecha entonces estamos seguros de que la conexión está activa (se le dice “viva” en muchos documentos sobre redes). El Cliente solamente necesita saber si la conexión está activa cuando envía una solicitud, para que ésta no rebote; en los demás momentos no le importa.
  4. El Windows puede ayudarnos a mantener la conexión activa. Si se lo pedimos puede enviar paquetes de reconocimiento cada “x” segundos. Los datos en el protocolo TCP/IP viajan en grupos conocidos como paquetes, los cuales están compuestos por una cabecera, los datos del usuario, y la cola. Si en un paquete no se envían datos del usuario entonces puede usarse para saber si una conexión está activa o no. IMPORTANTE: Estas instrucciones son solamente para usuarios avanzados, si no es tu caso ni lo intentes o podrías dejar a tu Windows inservible. No lo olvides: no lo intentes si no sabes muy bien lo que estás haciendo. El Windows viene con un programa llamado REGEDIT el cual nos permite modificar el Registro, también podríamos modificarlo con un archivo que tenga la extensión .REG o con algunos otros programas utilitarios. En el Registro del Windows hay una clave llamada “Parameters” que encontrarás en HKEY_LOCAL_MACHINE | System | CurrentControlSet | Services | Tcpip. A esa clave le puedes agregar los siguientes valores DWORD: KeepAliveInterval, que determina la frecuencia con la cual el Windows repite transmisiones “keepalive” (mantener viva) cuando no recibe respuesta, puedes ponerle 1, lo cual significa que enviará paquetes cada 1 segundo; KeepAliveTime, que determina los segundos que esperará el Windows desde que se terminó la última conexión o intento de reconocimiento para enviar reconocimiento, si por ejemplo le pones 60 eso significa que esperará que hayan transcurrido 60 segundos después de la última conexión o intento de reconocimiento antes de verificar si está activa; TcpMaxDataRetransmissiones, que determina cuantas veces como máximo se enviará un paquete antes de decidir que la conexión está muerta, su valor por defecto es de 5.

Múltiples dispositivos usando la red WiFi

Además del problema que podemos tener con las pérdidas de señal hay otro problema que inclusive puede llegar a ser peor: los usuarios querrán usar la red WiFi para conectar no solamente las computadoras que accederán a las bases de datos sino también tabletas, teléfonos celulares smart, televisores smart, relojes smart, y cualquier otro dispositivo habido o por haber que pueda conectarse a una red WiFi.

Entonces, no podrás evitar que a algún “genio” se le ocurra ver una película on-line mientras otros usuarios necesitan una red rápida. Es muy difícil evitar esas conexiones piratas y siempre tendrán algún muy buen motivo para hacerlas … y lo que conseguirán será que los tiempos de respuesta de las solicitudes a las bases de datos sean paupérrimos.

Conclusión:

 Es posible conectarse a bases de datos de Firebird a través de redes WiFi, pero si se desea un buen tiempo de respuesta el hardware debe ser de buena calidad y el software debe estar bien configurado.

Sin embargo, una buena red cableada siempre será mejor que una buena red WiFi.

Para deslindar responsabilidades siempre es una muy buena idea hacerle firmar un documento a tu cliente que diga algo como: “Para trabajar con bases de datos son preferibles las redes cableadas, las redes WiFi solamente tienen un buen desempeño cuando el hardware es de muy buena calidad y el software está correctamente configurado, en otro caso es una mala opción usarlas. Pero aún con una buena red WiFi siempre la red cableada será más rápida y más confiable. Mi recomendación por lo tanto es usar una red cableada.”

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

 

Los archivos temporales del Firebird

Deja un comentario

El Firebird a veces necesita crear archivos temporales, eso generalmente ocurre cuando en un comando SELECT se usa la cláusula ORDER BY y no existe un índice que pueda ser usado, o cuando ya no hay espacio disponible en la porción de memoria RAM que utiliza para los ordenamientos, o cuando se crean tablas temporales (o sea: tablas GTT) de gran tamaño.

Si el Servidor del Firebird recibe la orden de ejecutar un SELECT que contiene la cláusula ORDER BY y no hay un índice que pueda utilizar entonces evidentemente debe ordenar esas filas en algún lado para poder mostrarlas ordenadas.

¿Dónde se realiza ese ordenamiento?

El Firebird usa una porción de la memoria RAM a la cual llama Sort Buffer para realizar en ella los ordenamientos. Sin embargo, el espacio del Sort Buffer es limitado y en ocasiones puede ser insuficiente.

¿Qué sucede cuando no hay espacio suficiente en el Sort Buffer para realizar allí el ordenamiento?

Que el Firebird crea archivos temporales. Como no dispone de memoria RAM (la cual es rapidísima) para ordenar el resultado de la consulta entonces crea en el disco duro archivos temporales. Esto es mucho más lento que usar la memoria RAM pero funciona y no hay otra alternativa: hay que crear archivos temporales sí o sí.

¿Cuáles son los nombres de esos archivos temporales?

Todos los archivos temporales creados por el Firebird empiezan con los caracteres FB_ y dependiendo de su contenido serán los siguientes caracteres, por ejemplo si empieza con:

FB_QUERY_  significa que es un archivo temporal creado porque se usó la cláusula ORDER BY sin tener un índice disponible

FB_TABLE_ significa que se creó una tabla temporal (una tabla GTT)

¿Cómo puedo especificar dónde se crearán esos archivos temporales?

Por defecto, si el Firebird es iniciado como un servicio entonces los archivos temporales son creados en la carpeta temporal del Windows, normalmente en C:\WINDOWS\TEMP\ pero si se quiere crearlos en otras carpetas hay dos formas de hacerlo:

  1. Especificando las variables de entorno FIREBIRD_TMP, TEMP, TMP
  2. Cambiando la entrada TempDirectories del archivo FIREBIRD.CONF que se encuentra en la carpeta donde instalaste el Firebird

TEMP1

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

En la Captura 1. podemos ver como especificar una carpeta donde guardar los archivos temporales del Firebird que no sea la que utiliza el Windows. Por supuesto que la carpeta especificada (en este caso: E:\FIREBIRD_ARCHIVOS_TEMPORALES) debe existir y el nombre de la carpeta puede ser cualquiera, el nombre mostrado en la Captura 1. es solamente un ejemplo.

TEMP2

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

En la Captura 2. podemos ver como especificar cual será la carpeta temporal en el archivo FIREBIRD.CONF, recordando que debemos borrar el símbolo de numeral que se encuentra a la izquierda de la entrada TempDirectories ya que el símbolo # indica que lo que sigue a continuación es un comentario.

El autor de este blog recomienda que se especifique la carpeta de los archivos temporales en la entrada TempDirectories y que de ser posible se utilice un disco RAM para ese propósito.

¿Puedo tener más de una carpeta para guardar los archivos temporales?

Sí, sin problema, lo único que debes hacer es separarlas con un punto y coma, por ejemplo:

TempDirectories=E:\FIREBIRD_TEMP;F:\ARCHIVOS_TEMP_FIREBIRD;G:\FIREBIRD_TEMP

¿Puedo especificar el tamaño de las carpetas dónde se guardarán los archivos temporales?

Sí, si lo deseas puedes especificar inclusive el tamaño en bytes que se usará en cada carpeta, por ejemplo:

TempDirectories=E:\FIREBIRD_ARCHIVOS_TEMPORALES 100000000

o

TempDirectories=E:\FIREBIRD_TEMP 250000000;F:\TEMP_FILES 300000000;G:\MIS_TEMPORALES 100000000

¿Por qué los archivos temporales del Firebird a veces tienen un tamaño muy grande?

Porque el Firebird expande las columnas CHAR y VARCHAR a su tamaño especificado en la definición de la tabla. Muchos programadores saben que el Firebird no guarda en el disco duro el tamaño especificado en la tabla sino que guarda el contenido de esas columnas comprimido. Entonces saben que pueden especificar un tamaño mucho mayor al necesario sin problema. Por ejemplo, supongamos que la mayor longitud que necesitamos en una columna es de 850 bytes pero en la definición de la tabla usamos 1.000 bytes, 4.000 bytes ó 12.500 bytes; estará todo bien, porque el Firebird nunca guardará más de 850 bytes en el disco duro, sin importar como se definió la columna. Eso en general es algo muy bueno.

Sin embargo, al hacer un SORT a esa columna la cosa cambia, porque allí sí el Firebird utiliza el tamaño usado en la definición de la columna.

De esta manera, inclusive a veces podríamos encontrarnos que tenemos un archivo temporal … cuyo tamaño es mayor al tamaño de la Base de Datos.

Así que, a no exagerar con el tamaño de las columnas CHAR y VARCHAR si existe la posibilidad de que alguna vez sean usadas en la cláusula ORDER BY de un comando SELECT.

¿Puedo borrar los archivos temporales?

Sí, si el Firebird no los está usando. El Windows no permite que se borre un archivo si algún programa lo está usando, esa es una muy buena medida de precaución.

Entonces, puedes intentar borrar cualquier archivo temporal. Si tuviste éxito eso significa que ningún programa lo estaba usando. Si no pudiste borrarlo entonces tendrás que esperar hasta que deje de ser usado.

Conclusión:

A veces el Firebird necesita crear archivos temporales en el disco duro. Nosotros podemos decirle cuales carpetas debe utilizar para eso e inclusive la cantidad de bytes que puede usar en cada carpeta.

Para aumentar la velocidad de los ordenamientos lo recomendable es usar un disco RAM, si eso no es posible entonces lo recomendable es que los archivos temporales se guarden en un disco duro distinto al usado para guardar las bases de datos.

Artículos relacionados:

Creando y usando tablas temporales

Usando un disco RAM para aumentar la velocidad

Acelerando los SORT

Configurando al Firebird

¿En cuál carpeta tener las bases de datos?

El índice del blog Firebird21

El foro del blog Firebird21

Older Entries

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 331 seguidores