Evaluar bases de datos: qué demuestran las pruebas

Evalúa la compatibilidad con PostgreSQL, el aislamiento, la durabilidad y los límites de las pruebas con esta lista de comprobación para bases de datos.

Ernest Bursa

Ernest Bursa

Founder · · 7 min de lectura
A woman in a grey startupkit sweatshirt comparing two cards beside a closed laptop in a sunlit garage.

Una lista de comprobación para evaluar bases de datos debe vincular las reglas de las que depende tu negocio con pruebas de que la base de datos puede respetarlas. Comprueba por separado la compatibilidad del cliente, el comportamiento de SQL, las transacciones concurrentes y la durabilidad. Anota la compilación exacta, la configuración, los resultados observados y las cuestiones pendientes antes de confiar al sistema los registros que serán tu fuente de referencia.

El informe de Jepsen sobre ParticleDB del 31 de octubre ofrece un ejemplo reciente de por qué conviene distinguir estas pruebas. La investigación, financiada por Orkes, abarcó instalaciones de un solo nodo con las versiones 1.1.4 a 1.1.18.11.rc-22 y describió 96 problemas. En la última compilación probada parecían resueltos todos salvo diez. Jepsen atribuye a Orkes la afirmación de haber corregido los problemas restantes en 1.1.19-rc.13, mientras que el artículo de Orkes del 30 de octubre los da por corregidos a partir de 1.1.19. Esas compilaciones posteriores quedaron fuera de las pruebas publicadas por Jepsen.

Para tu evaluación, lo relevante es qué demuestra un resultado sobre tu aplicación. El método que sigue es una propuesta, no una prueba de bases de datos que hayamos realizado.

Empieza por una regla del negocio

Escribe una condición que deba seguir cumpliéndose cuando se solapan las peticiones o se detiene un proceso. Ese es tu requisito inicial, que suele llamarse invariante.

En un producto de reservas, las reservas confirmadas no deben superar el aforo. En un libro de cuentas, una transferencia no debe dejar confirmado solo uno de sus dos asientos. Elige reglas de tu aplicación y define también qué puede ver el usuario tras un éxito o un error.

Indica dónde se aplica cada regla: en una restricción de la base de datos, una transacción, el código de la aplicación o un sistema externo. Una base de datos no puede hacer cumplir una regla que tu implementación nunca expresa. Identificarlo también te ayuda a investigar un fallo sin atribuírselo de inmediato al motor de almacenamiento.

Recoge pruebas separadas para cada capa

Utiliza esta tabla para planificar la evaluación. Cada fila responde a una pregunta distinta; superar una comprobación no resuelve las de las demás filas.

Capa Pruebas que debes recoger Qué sigue sin demostrarse
Compatibilidad del protocolo y de la API Operaciones reales del controlador y del pool de conexiones, sentencias preparadas, tipos devueltos y gestión de errores Resultados SQL correctos o garantías de las transacciones
SQL y restricciones Consultas representativas y escrituras deliberadamente inválidas, con sus resultados esperados y el momento de comprobación de las restricciones Comportamiento cuando se solapan transacciones
Transacciones concurrentes Operaciones solapadas, evaluadas según el nivel de aislamiento documentado y la regla del negocio Conservación de las escrituras confirmadas tras un fallo
Durabilidad y recuperación Qué commits confirmados se conservan después de los fallos concretos que has probado Comportamiento no probado ante cortes de corriente o en la replicación
Versión y configuración Huella de la compilación o de la imagen, versión del controlador, esquema, ajustes, topología y revisión de las pruebas Comportamiento equivalente en otra compilación o instalación
Comprobaciones pendientes Requisitos sin probar, correcciones anunciadas, responsable de repetir las pruebas y consecuencias para la adopción Un resultado favorable cuando aún faltan pruebas

Conserva para cada resultado el estado inicial, las operaciones, el resultado esperado y el observado. Guarda suficientes registros o un historial de transacciones para que otro desarrollador pueda cuestionar tu interpretación. Un panel en verde aporta poco si nadie puede identificar qué comprobó el conjunto de pruebas.

Comprueba la compatibilidad con PostgreSQL desde tu aplicación

Trata la compatibilidad como un conjunto de requisitos. La documentación del protocolo de PostgreSQL describe los mensajes que intercambian clientes y servidores. Poder conectarse mediante ese protocolo solo cubre una parte de lo que necesita tu aplicación.

Ejecuta las operaciones del controlador que vayas a utilizar y comprueba después las funciones SQL que necesitan. Incluye restricciones, valores nulos, límites numéricos y gestión de errores cuando afecten a tus reglas. Ejecuta las consultas reales de la aplicación, incluidas las operaciones menos frecuentes, como una exportación administrativa.

Si comparas resultados con PostgreSQL, define primero las diferencias aceptables. Las filas sin ordenar no tienen por qué llegar en el mismo orden. La precisión numérica, el momento en que se comprueban las restricciones y la prioridad de los errores requieren criterios propios. Clasifica cada diferencia según las garantías documentadas y las necesidades de tu aplicación, en lugar de considerar un defecto cualquier discrepancia.

Comprueba una regla de aforo con un ejemplo

Imagina un taller hipotético con 30 plazas y 29 reservas confirmadas. Cada transacción de reserva cuenta las reservas confirmadas, inserta una nueva solo si quedan plazas y después ejecuta el commit. Es un ejemplo ficticio: no lo hemos ejecutado en ninguna base de datos.

Planifica una evaluación con dos clientes independientes:

  1. Inicia ambas transacciones a la vez. Si las dos pueden contar 29 reservas antes de que alguna inserte una nueva, conserva ese historial. Registra los bloqueos si el motor serializa antes el acceso.
  2. Deja que cada transacción intente su inserción condicional y su commit. Registra por separado los resultados de las sentencias, las confirmaciones de commit y los errores.
  3. Lee el estado final en la fuente de referencia mediante una conexión nueva y comprueba la regla de aforo.
  4. Si una transacción falla con un error de serialización, repite toda la transacción de lectura, comprobación y escritura. Anota la decisión que resulte.

Con una garantía de serializabilidad, el efecto de las transacciones confirmadas debe corresponder al de alguna ejecución secuencial. Con esta lógica de transacción, dos confirmaciones nuevas que eleven el total a 31 no cumplirían esa garantía. En cambio, una transacción podría fallar y, al repetirse, comprobar que el taller está completo.

La documentación sobre aislamiento de PostgreSQL explica tanto la serializabilidad como la necesidad de repetir transacciones enteras. También indica que Repeatable Read puede permitir anomalías de serialización. Si eliges garantías más débiles que permitan esa interacción problemática, el exceso de reservas indica que tu aplicación y esas garantías no encajan; por sí solo no demuestra un error de la base de datos.

Registra por separado los casos en que el cliente agota el tiempo de espera. Si la conexión se pierde durante el commit, el cliente puede no saber si se guardó su reserva. Resuelve esa incertidumbre mediante un identificador de operación estable antes de repetir la acción de negocio.

En este diseño, guarda el identificador de forma atómica junto con la reserva, exige que sea único y reutilízalo en los reintentos. Que un registro no aparezca temporalmente no demuestra por sí solo que se haya revertido la transacción original tras agotarse el tiempo de espera. El nivel de aislamiento de la base de datos tampoco impide por sí solo que tu aplicación envíe correos de confirmación duplicados o cobre un pago dos veces.

Vincula cada garantía de durabilidad con un fallo concreto

Pregunta qué promete la base de datos al confirmar un commit con la configuración que piensas desplegar. Después elige pruebas que comprueben esa promesa.

La documentación sobre commit asíncrono de PostgreSQL ofrece un ejemplo concreto: esa configuración puede confirmar transacciones que se pierdan después en una caída. Es una contrapartida documentada, no un incumplimiento de la garantía configurada.

En un entorno de evaluación aislado, anota los identificadores de las operaciones confirmadas, provoca el fallo elegido y compara los registros recuperados. Identifica las operaciones de resultado incierto por separado de los commits confirmados. Detener un proceso del servidor no reproduce un corte de corriente en el almacenamiento, y reiniciar un nodo no prueba la conmutación a una réplica. La documentación sobre fiabilidad de PostgreSQL explica por qué los componentes de almacenamiento influyen en la persistencia.

Exige pruebas que correspondan a la instalación que valoras. Si necesitas conmutación entre regiones ante fallos, un reinicio local satisfactorio deja ese requisito sin respuesta.

Distingue entre corregir un fallo y volver a probarlo

La notificación de una corrección por parte del proveedor es información útil. Conserva su atribución y la versión exacta junto al resultado hasta que se haya vuelto a comprobar el comportamiento requerido.

Anota qué caso de reproducción se volvió a ejecutar, si también se ejecutó el resto de la carga de trabajo y si cambió la compilación o la configuración. Distingue resultados como prueba superada, prueba fallida, corrección anunciada por el proveedor, pendiente de repetir la prueba y sin probar. Superar un caso de reproducción no demuestra que se cubran todos los casos relacionados; superar un conjunto más amplio de pruebas tampoco demuestra una corrección universal.

Haz que la falta de pruebas cambie la decisión. Supón que una base de datos supera tus comprobaciones SQL, pero para la instalación que necesitas no hay pruebas de que las escrituras confirmadas sobrevivan a una conmutación por fallo. Si conservarlas es obligatorio, mantén los registros de reservas que sirven de referencia en el almacenamiento actual. Aun así, podrías evaluar la nueva base de datos para un índice de búsqueda que se pueda reconstruir, con requisitos propios. No diluyas el requisito pendiente en una puntuación global y apruebes ambos usos.

Documenta una decisión que otro desarrollador pueda revisar

Termina con el uso propuesto, las garantías necesarias, la instalación exacta que has evaluado, los enlaces a las pruebas y los requisitos pendientes. Indica quién acepta cada riesgo restante y qué nuevos resultados cambiarían la decisión. Anota las mediciones de rendimiento con la misma configuración para que las comparaciones de velocidad sigan siendo relevantes.

Si después apruebas una migración, nuestro artículo sobre la migración desde Deno Deploy trata el trabajo posterior de probar el destino y preparar el cambio. La decisión de este artículo llega antes: si hay pruebas suficientes para confiar a esta base de datos esa función en tu aplicación. Empieza por la regla cuyo incumplimiento no te puedes permitir y deja abierta la decisión de adoptar la base de datos hasta disponer de las pruebas necesarias.

Artículos relacionados

Prueba Kit durante 30 días.

Contratación, informes de seguridad y formación en una sola cuenta, para equipos donde nada de eso es un trabajo a tiempo completo. 30 días gratis, con tarjeta. Cancela antes de que termine y no pagas nada.

Empieza gratis