1 puntos por GN⁺ 2024-09-13 | 1 comentarios | Compartir por WhatsApp
  • Durante el último año, se ha buscado comprender a fondo cómo ejecutar aplicaciones Rails con SQLite de manera rápida y estable
  • En ese proceso se aprendieron varias lecciones, y se quieren compartir
  • Se explicarán las causas de los problemas y cómo resolverlos

Problemas de SQLite y Rails

  • De forma predeterminada, una aplicación Rails con SQLite no queda lista para usarse tal cual
  • Con algunos ajustes y afinación, se puede lograr una aplicación rápida y estable
  • En Rails 8, el objetivo es que quede lista para producción solo con la configuración por defecto

Aplicación de demostración "Lorem News"

  • Se usará una aplicación de demostración llamada "Lorem News" para explicar los problemas y las soluciones
  • Esta aplicación es un clon de Hacker News, donde los usuarios pueden escribir publicaciones y comentarios

Pruebas de rendimiento

  • Se probó el rendimiento usando el CLI de pruebas de carga oha y una ruta de benchmarking dentro de la aplicación
  • El rendimiento se midió con solicitudes individuales y concurrentes

Problema principal: excepciones SQLITE_BUSY

  • SQLite usa bloqueos de escritura para permitir solo una operación de escritura a la vez
  • Cuando varias conexiones intentan obtener el bloqueo de escritura al mismo tiempo, ocurre la excepción SQLITE_BUSY
  • Para resolver este problema, se deben usar transacciones inmediatas

Transacciones inmediatas

  • De forma predeterminada, SQLite usa el modo de transacción diferida
  • Si se usan transacciones inmediatas, se intenta obtener el bloqueo de escritura de inmediato y, si falla, se puede reintentar
  • Con la gem sqlite3-ruby, se puede configurar el modo de transacción predeterminado en modo inmediato

Configuración del timeout

  • La configuración de timeout en el archivo database.yml puede reducir las excepciones SQLITE_BUSY
  • Se puede usar la configuración busy_timeout de SQLite para reintentar el bloqueo de escritura

Problema del GVL (bloqueo global de la VM)

  • La gem sqlite3-ruby no libera el GVL al llamar al código C de SQLite
  • Esto perjudica el rendimiento de concurrencia
  • Se puede usar busy_handler para liberar el GVL y mejorar el rendimiento

Reimplementación de busy_timeout

  • Se reimplementó busy_timeout para que todas las consultas se reintenten con la misma frecuencia
  • Esto evita que las consultas más antiguas expiren por timeout

Mejora de rendimiento

  • Para mejorar el rendimiento, se deben aplicar las siguientes configuraciones
    • usar transacciones inmediatas
    • configurar el timeout
    • usar busy_handler
    • usar el modo WAL (Write-Ahead Logging)
    • separar los pools de conexiones de lectura y escritura

Resumen de GN⁺

  • Se abordan los problemas de rendimiento de las aplicaciones Rails con SQLite y sus soluciones
  • El rendimiento puede mejorar mediante transacciones inmediatas, configuración de timeout, liberación del GVL, uso del modo WAL y separación de los pools de conexiones de lectura y escritura
  • Este artículo será muy útil para desarrolladores que usan SQLite y Rails
  • Para otros proyectos con funciones similares, se recomiendan PostgreSQL y MySQL

1 comentarios

 
GN⁺ 2024-09-13
Comentarios de Hacker News
  • Introducción al proyecto Litestack de Oldmoe

    • Quienes usan SQLite y Rails deberían revisar el proyecto Litestack de Oldmoe
    • Litestack es una gema de Ruby que aprovecha la potencia de SQLite para ofrecer una infraestructura de datos para aplicaciones web
    • Ofrece en un solo paquete una base de datos SQL, caché rápida, una potente cola de trabajos, un bróker de mensajes confiable, un motor de búsqueda de texto completo y una plataforma de métricas
    • Lo estoy usando en un proyecto actual y estoy muy satisfecho
  • Agradecimiento por el artículo detallado

    • Es información útil para quienes quieren escalar aplicaciones web con SQLite
    • Puede aplicarse más allá de Rails, también en otros frameworks
    • Gracias al autor
  • Recomendado para quienes trabajan con SQLite

    • Independientemente del lenguaje o framework que usen, quienes trabajen con SQLite deberían leer este artículo
    • Aborda problemas que hace unos años uno tenía que resolver por su cuenta
    • Gracias al autor
  • Pregunta sobre un sistema de analítica FOSS

    • Estoy creando un sistema de analítica FOSS fácil de instalar
    • Quiero enviar los datos de eventos a una base de datos SQLite separada para aislarlos de los datos de la app principal
    • Me preocupa la escalabilidad para manejar más de 1000 eventos por segundo
    • Estoy considerando guardar los eventos en la memoria del servidor y escribirlos en lote una vez por segundo
    • Pido opiniones sobre si esta es una forma razonable de resolver muchos de los problemas de escritura en SQLite
  • Problema de GVL en la gema sqlite3-ruby

    • La gema sqlite3-ruby no libera el GVL durante las llamadas a SQLite
    • En la mayoría de los casos, esto parece una decisión razonable
    • Es posible que en las extensiones de Python se haya diseñado de otra manera
    • La gema extralite libera el GVL durante los bloqueos, suele ser más rápida y no tiene problemas de concurrencia
  • Configuración de un servicio web personal

    • Algunas configuraciones que uso en un servicio web personal:
      • PRAGMA journal_mode = WAL
      • PRAGMA busy_timeout = 5000
      • PRAGMA synchronous = NORMAL
      • PRAGMA cache_size = 1000000000
      • PRAGMA foreign_keys = true
      • PRAGMA temp_store = memory
      • Uso transacciones BEGIN IMMEDIATE
  • Pregunta sobre Django

    • Este artículo es excelente
    • Me pregunto si existe una solución similar para Django
    • ArchiveBox usa SQLite a través de Django y con frecuencia sufre los problemas mencionados para Rails
    • Sería bueno tener una solución a nivel de capa SQLite que no serialice todas las escrituras a través de otros canales de la app
  • Dudas sobre la configuración predeterminada de busy_timeout

    • Es un artículo muy informativo y bien escrito
    • Me pregunto por qué el método predeterminado de busy_timeout tiene una demora que castiga a las consultas más antiguas
    • También me pregunto por qué eso tendría sentido como configuración predeterminada
  • Opinión sobre usar SQLite con Rails

    • Me gustan SQLite y Rails, pero esto se parece a usar MS Access en producción
  • Agradecimiento por resolver problemas de integración con Rails

    • Siempre da gusto ver que alguien resuelva problemas de integración y ayude a los demás
    • Ojalá estas correcciones se incluyan en la configuración predeterminada de Rails
    • Administro una app en Rails y hace unos años me cambié a Postgres; estoy muy satisfecho
    • Aun así, es bueno que existan alternativas, y sigo usando SQLite para otras tareas