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

 

 

 

Un artículo incompleto

Deja un comentario

Con este  tema de fin de año, sin querer se publicó un artículo que aún no debería haberse publicado por encontrarse incompleto.

Empecé a escribirlo, establecí la fecha y hora en que debería publicarse, y luego me olvidé de él, es que con tantas actividades, ni me acordé que estaba incompleto y que ya estaba marcado para ser publicado. Hace un rato, revisando el blog, me encontré con la sorpresa de que había sido publicado y aún no debería.

Así que lo actualicé, lo completé, y ahora finalmente sí está listo para ser leído:

Detectando y eliminando filas duplicadas

Si ya lo habías leído, vuelve a hacerlo, ahora ya está completo.

Y disculpas.

 

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