Volver al inicio

Diseñando DB OLTP en Rust: principios

El artículo describe los principios de diseño de una base de datos OLTP desde cero en Rust: restrictivo por defecto, contract-first vía traits, asincronía híbrida. Implementado almacenamiento unificado, MVCC, WAL. Enfoque en predictibilidad y confiabilidad para producción.

DB OLTP desde cero: arquitectura e implementación en Rust
Advertisement 728x90

Arquitectura de Bases de Datos OLTP: De Principios a Implementación en Rust

Se han implementado subsistemas clave del motor OLTP: almacenamiento unificado en un solo archivo por base de datos, almacenamiento respaldado en disco con MVCC de registro UNDO, recuperación basada en WAL y ARIES, un BufferPool compartido, un motor en memoria y un protocolo pgwire compatible con PostgreSQL. El código es funcional pero requiere pruebas de carga y estabilización de casos límite. No es un producto final, sino una etapa temprana con contratos establecidos.

Principios de Diseño Fundamentales

El proyecto se basa en reglas estrictas para la toma de decisiones. Cada nueva decisión debe adherirse a ellas o justificar cualquier desviación.

Restrictivo por Defecto

Los componentes tienen límites explícitos con comportamiento de fallo cerrado en lugar de limitación. Esto garantiza predictibilidad bajo carga.

Google AdInline article slot

| Componente | Límite | Acción ante Violación | SQLSTATE |

|-----------|---------|------------------------|----------|

| BufferPool | buffer_pool_size_mb | Evicción (CLOCK), vaciado WAL primero | — |

Google AdInline article slot

| TxnWriteSet | txn_max_write_set_mb | Rechazar DML | 54023 |

| UndoStore | undo_max_size_mb | Rechazar escrituras | 53100 |

| Pool de conexiones | max_connections | Rechazar nuevas conexiones | 53300 |

Google AdInline article slot

| Tiempo límite de sentencia | statement_timeout_ms | Cancelar consulta | 57014 |

| Antigüedad de snapshot | max_snapshot_age | Forzar cierre de snapshots obsoletos | 40001 |

El fallo cerrado proporciona códigos SQLSTATE claros para lógica de reintento de aplicaciones o cortacircuitos.

Enfoque Contrato-Primero

Los contratos arquitectónicos se definen en traits de Rust: TableEngine, PageProvider, TransactionLogSink, StorageIo. Esto evita la desviación de implementación al hacer cumplir invariantes en tiempo de compilación.

¿Por qué Rust?

Rust fue elegido por su latencia predecible, control de asignación de memoria y seguridad de tipos. Send/Sync en límites async/síncronos, errores explícitos en lugar de problemas en tiempo de ejecución. C++ requiere disciplina adicional, mientras que Go no es adecuado debido al GC para la latencia de cola en OLTP.

Separación de Responsabilidades

La base de datos funciona como un motor de datos sin lógica de negocio: sin disparadores, PL/pgSQL o procedimientos almacenados inicialmente. Las funciones definidas por el usuario pueden agregarse más tarde con aislamiento y sin efectos secundarios.

Asincronicidad Híbrida

  • Capa de red/pgwire: asíncrona (aceptar, TLS, enviar).
  • Núcleo (ejecución de consultas, almacenamiento, WAL, MVCC): síncrono para corrección y depuración.
  • El límite es unidireccional a través de un puente.

StorageIo está abstraído para permitir E/S asíncrona futura sin reescribir la lógica de transacciones.

| Capa | Tiempo de Ejecución | Ejemplos |

|------|---------|---------|

| Red/Protocolo | asíncrono | pgwire, TLS |

| Ejecución de Consultas | síncrono | plan, ejecutar |

| Almacenamiento/WAL | síncrono (E/S asíncrona después) | HeapStore, BufferPool |

| MVCC/Transacciones | síncrono | snapshot, bloqueos |

Compatibilidad con PostgreSQL

Pgwire permite la integración con controladores y ORMs sin migraciones de cliente. La compatibilidad es a nivel de cable a través de una capa límite, sin copiar internos de PostgreSQL (montón MVCC, VACUUM). El núcleo conserva libertad arquitectónica.

Restricciones de Plataforma y Fiabilidad

Solo Linux para centrarse en io_uring y eBPF sin compromisos multiplataforma. Prioridades: sin corrupción de datos, reversión segura de optimizaciones, resiliencia a entrada de usuario, seguridad integrada.

Conclusiones Clave

  • Restrictivo por Defecto con fallo cerrado para predictibilidad bajo carga.
  • Contrato-Primero mediante traits de Rust para control de invariantes.
  • Asíncrono/síncrono híbrido: estabilidad del núcleo antes de aceleración de E/S.
  • Compatibilidad pgwire sin copiar internos de PostgreSQL.
  • Motor de datos sin lógica de negocio para pureza y capacidad de prueba.

— Editorial Team

Advertisement 728x90

Leer después