Introducción

Los usuarios de la biblioteca SQLite, en particular los desarrolladores de aplicaciones, que desean acceder a una base de datos SQLite desde diferentes sistemas conectados por una red a menudo se ven tentados a simplemente abrir una conexión de base de datos especificando un nombre de archivo que hace referencia a un archivo de base de datos en algún lugar dentro de un sistema de archivos de red. (“base de datos remota” aquí) Se accede a este “archivo” por medio de las API del sistema operativo que permiten la ilusión de E / S desde / hacia un archivo local. La ilusión es buena pero imperfecta en aspectos importantes.

Este enfoque simple de “base de datos remota” generalmente no es la mejor manera de usar una sola base de datos SQLite de múltiples sistemas (incluso si parece que “funciona”), ya que a menudo conduce a varios tipos de problemas y dolores. Debido a que estos problemas son inevitables con algunos usos, pero no son frecuentes ni repetibles, corresponde a los desarrolladores de aplicaciones no depender del éxito de las primeras pruebas para decidir que el uso de la base de datos remota funcionará como se desea.

Problemas que surgen con archivos de bases de datos remotas

Este diagrama muestra los componentes y sus vínculos para referencia en la siguiente discusión:

ClienteSolicitudSQLiteBase de datosMotorBase de datosArchivo (s)API de SQLiteLlamadasMotor de base de datosE / S de archivos

Los problemas surgen de las propiedades y la utilización de los dos canales de datos / control entre los tres bloques anteriores.

Volumen de tráfico del canal

El canal “API Call” transporta menos información que el canal “File I / O”. Las llamadas a la API para enviar consultas o especificar la modificación de los datos normalmente requieren que se pasen de un lado a otro sustancialmente menos bits que los que se transfieren hacia / desde el archivo de la base de datos para almacenar o encontrar los datos. La recuperación de los resultados de la consulta normalmente requerirá mucho más tráfico de archivos que el tráfico de API porque los datos que se devuelven rara vez se encuentran sin leer datos no solicitados.

Canal de Banda ancha

El canal API Call opera a velocidades de memoria principal del procesador (Giga-palabras / segundo), y los datos a menudo pasan por referencia (y por lo tanto no se copian). Por el contrario, incluso los canales de E / S de archivos más rápidos son más lentos. Requieren que los datos se copien, generalmente en un medio que requiera serialización de bits. Para los medios magnéticos giratorios, las transferencias esperan la rotación del plato y el movimiento del cabezal, luego están limitadas por la velocidad de giro.

Cuando el canal de E / S de archivos incluye una conexión de red (además de algunas E / S de archivos genuinas en su extremo lejano), se impone una lentitud adicional. Incluso cuando la tasa de transferencia sin procesar no limita el ancho de banda, el tráfico debe empaquetarse y almacenarse en búfer en ambos extremos. Las capas adicionales de controladores de E / S añaden retrasos en la programación. Sin embargo, las transferencias lentas son el problema menos significativo con los sistemas de archivos de red.

Fiabilidad del canal

El canal “API Call” es altamente confiable, en la medida en que las tasas de error no se indican y se ignoran como insignificantes. El canal falla solo cuando el sistema pierde energía (excepto meteoritos, etc.)

El canal “File I / O”, cuando llega directamente a un dispositivo de almacenamiento local, también es muy confiable. (El MTBF de almacenamiento giratorio excede 1 millón de horas y la NVRAM dura más). Los dispositivos locales también tienen una característica que es fundamental para permitir que el software de administración de bases de datos se diseñe para garantizar el comportamiento ACID: cuando se hayan completado todas las escrituras del proceso en el dispositivo, (cuando POSIX fsync () o Windows FlushFileBuffers () devuelve), el sistema de archivos ha almacenado los datos “escritos” o lo hará antes de almacenar cualquier dato escrito posteriormente.

Cuando el aparato del sistema de archivos de red y las capas de software se interponen entre los clientes del sistema de archivos y un sistema de archivos sobre un dispositivo de almacenamiento real, se introducen importantes fuentes de fallas y mal comportamiento. Si bien las transferencias de datos de red se controlan bien, los paquetes de transferencia no llegan todos de manera confiable a su destino una vez enviados. Algunos paquetes son golpeados por otros paquetes y deben reenviarse. En condiciones de golpe de paquetes, los reintentos repetidos pueden imponer retrasos que exceden lo que se necesita para que datos similares lleguen al almacenamiento local. Algunas partes de lo que escribe un cliente pueden terminar almacenadas fuera del orden de tiempo en relación con otras partes escritas.

Debido al desorden y la pérdida absoluta de datos que se producen en las escrituras del sistema de archivos de red, es fundamental que los conjuntos de escrituras de archivos se puedan saber con precisión antes de que comience un conjunto posterior de escrituras de archivos. Esta garantía se obtiene mediante el uso de funciones del sistema operativo fsync () (o equivalente) sólidamente diseñadas e implementadas correctamente. Desafortunadamente para algunas aplicaciones, la operación de sincronización del sistema de archivos de red puede ser menos robusta que la sincronización del sistema de archivos local. Lograr una sincronización sólida frente a los errores de transporte de paquetes de red es difícil y, a veces, las salvaguardas se relajan a favor del rendimiento.

La conclusión es que la confiabilidad de la sincronización del sistema de archivos de red varía entre las implementaciones e instalaciones. Los supuestos de diseño en los que se basa pueden tener más true donde se prueba una aplicación que donde se confía. Confíe en él bajo su responsabilidad (y la de sus clientes). Consulte Cómo dañar los archivos de su base de datos.

Problemas de rendimiento y confiabilidad

A partir del diagrama y la discusión anteriores, es obvio que el rendimiento (también conocido como “velocidad”) se degrada mediante la inserción de un enlace de red en uno de los dos canales. La consideración de los volúmenes de tráfico relativos entre el canal de llamada de API y el canal de E / S de archivo revela que dicha inserción tendrá un impacto menor en el rendimiento en el canal de llamada de API.

La consideración del impacto de la confiabilidad es más fácil, con un resultado más claro: insertar un enlace de red en el canal de llamada API también puede resultar en fallas en las llamadas en ocasiones. Pero si la Aplicación Cliente se ha molestado en utilizar correctamente las transacciones SQL / SQLite, tales fallas solo harán que una transacción falle y se revierta, sin comprometer la integridad de los datos. Por el contrario, si el enlace de red se inserta en el canal de E / S de archivos, las transacciones pueden fallar (como para la inserción de la llamada API) pero con el efecto adicional de que la base de datos remota está dañada.

Estos problemas de falta de fiabilidad de la red se pueden mitigar, por completo o en un grado aceptable, mediante el uso de SQLite en modo de reversión. Sin embargo, la biblioteca SQLite no se prueba en escenarios a través de una red, ni eso es razonablemente posible. Por lo tanto, se realiza el uso de una base de datos remota. a riesgo del usuario.

Recomendaciones

Generalmente, si sus datos están separados de la aplicación por una red, desea utilizar una base de datos cliente / servidor. Esto se debe al hecho de que el motor de la base de datos actúa como un filtro que reduce el ancho de banda en el tráfico de la base de datos.

Si sus datos están separados de la aplicación por una red, desea que el enlace de bajo tráfico esté a través de la red, no el enlace de alto tráfico. Esto significa que el motor de la base de datos debe estar en la misma máquina que la propia base de datos. Tal es el caso de una base de datos cliente / servidor como PostgreSQL. SQLite es diferente en que el motor de la base de datos se ejecuta en la misma máquina que la aplicación, lo que obliga al enlace de mayor tráfico a atravesar la red en escenarios de bases de datos remotas. Eso normalmente resulta en un rendimiento más bajo.

Los sistemas de archivos de red no admiten la capacidad de realizar lecturas y escrituras simultáneas y, al mismo tiempo, mantener la coherencia de la base de datos. Entonces, si tiene varios clientes en varias máquinas diferentes que necesitan realizar lecturas y escrituras simultáneas en la base de datos, tiene estas opciones:

1. Utilice un motor de base de datos cliente / servidor. PostgreSQL es una excelente elección. Una variación de esto es:

2. Aloje una base de datos SQLite en modo WAL, pero realice todas las lecturas y escrituras de los procesos en la misma máquina que almacena el archivo de la base de datos. Implemente un proxy que se ejecute en la máquina de la base de datos que transmita solicitudes de lectura / escritura de máquinas remotas.

3. Utilice SQLite en modo de reversión. Esto significa que puede tener varios lectores simultáneos o un solo escritor, pero no lectores y escritores simultáneos.

Los programadores de aplicaciones deben ser conscientes de la posibilidad de que los usuarios de su aplicación elijan utilizar una base de datos remota si pueden hacerlo. A menos que se haya efectuado una de las opciones anteriores, o una a la vez, se utilice el acceso exclusivo, un programador debe considerar bloquear esa elección a menos que la confiabilidad sea de poca importancia.

Resumen

Elija la tecnología adecuada para usted y sus clientes. Si sus datos se encuentran en una máquina diferente a la de su aplicación, entonces debería considerar una base de datos cliente / servidor. SQLite está diseñado para situaciones en las que los datos y la aplicación coexisten en la misma máquina. Aún se puede hacer que SQLite funcione en muchas situaciones de bases de datos remotas, pero una solución cliente / servidor generalmente funcionará mejor en ese escenario.