1 pontos por GN⁺ 2024-09-13 | 1 comentários | Compartilhar no WhatsApp
  • Ao longo do último ano, houve um esforço para compreender profundamente como executar aplicações Rails com SQLite de forma estável e com bom desempenho
  • Nesse processo, várias lições foram aprendidas, e a intenção é compartilhá-las
  • Serão explicadas as causas dos problemas e como resolvê-los

Problemas entre SQLite e Rails

  • Por padrão, uma aplicação Rails usando SQLite não fica pronta para uso imediatamente
  • Com alguns ajustes e refinamentos, é possível criar uma aplicação estável e com bom desempenho
  • No Rails 8, a meta é fazer com que a configuração padrão já esteja pronta para produção

Aplicação de demonstração "Lorem News"

  • Será usada uma aplicação de demonstração chamada "Lorem News" para explicar os problemas e as soluções
  • Essa aplicação é um clone do Hacker News, no qual os usuários podem criar postagens e comentários

Testes de desempenho

  • O desempenho é testado com a CLI de load testing oha e com uma rota de benchmarking dentro da aplicação
  • O desempenho é medido tanto com requisições individuais quanto com requisições simultâneas

Principal problema: exceção SQLITE_BUSY

  • O SQLite usa bloqueio de escrita para permitir apenas uma operação de gravação por vez
  • Quando várias conexões tentam obter o bloqueio de escrita ao mesmo tempo, ocorre a exceção SQLITE_BUSY
  • Para resolver esse problema, é necessário usar transações imediatas

Transações imediatas

  • Por padrão, o SQLite usa o modo de transação adiada
  • Ao usar transações imediatas, a tentativa de obter o bloqueio de escrita acontece imediatamente, e em caso de falha é possível tentar novamente
  • Com a gem sqlite3-ruby, é possível definir o modo padrão de transação como imediato

Configuração de timeout

  • A configuração de timeout no arquivo database.yml pode reduzir as exceções SQLITE_BUSY
  • É possível usar a configuração busy_timeout do SQLite para tentar novamente ao disputar o bloqueio de escrita

Problema do GVL (Global VM Lock)

  • A gem sqlite3-ruby não libera o GVL ao chamar o código C do SQLite
  • Isso prejudica o desempenho em cenários concorrentes
  • É possível usar busy_handler para liberar o GVL e melhorar o desempenho

Reimplementação de busy_timeout

  • busy_timeout foi reimplementado para que todas as consultas façam novas tentativas com a mesma frequência
  • Isso evita que consultas mais antigas estourem o timeout

Melhorias de desempenho

  • Para melhorar o desempenho, é preciso aplicar as seguintes configurações
    • usar transações imediatas
    • configurar timeout
    • usar busy_handler
    • usar o modo WAL (Write-Ahead Logging)
    • separar os pools de conexão de leitura e escrita

Resumo do GN⁺

  • O texto aborda problemas de desempenho em aplicações Rails com SQLite e suas soluções
  • O desempenho pode ser melhorado com transações imediatas, configuração de timeout, liberação do GVL, uso do modo WAL e separação dos pools de conexão de leitura e escrita
  • Este artigo será muito útil para desenvolvedores que usam SQLite e Rails
  • Outros projetos recomendados com funcionalidades semelhantes são PostgreSQL e MySQL

1 comentários

 
GN⁺ 2024-09-13
Comentários do Hacker News
  • Apresentação do projeto Litestack, do Oldmoe

    • Quem usa SQLite e Rails precisa conhecer o projeto Litestack, do Oldmoe
    • Litestack é uma gem Ruby que aproveita o poder do SQLite para fornecer a infraestrutura de dados de aplicações web
    • Oferece banco de dados SQL, cache rápido, fila de tarefas robusta, broker de mensagens confiável, mecanismo de busca full-text e plataforma de métricas em um único pacote
    • Estou usando no meu projeto atual e estou muito satisfeito
  • Agradecimento pelo artigo detalhado

    • É uma informação útil para quem quer escalar aplicações web com SQLite
    • Também pode ser aplicado a outros frameworks além de Rails
    • Agradecimentos ao autor
  • Recomendação para quem trabalha com SQLite

    • Independentemente da linguagem ou framework usado, quem trabalha com SQLite deveria ler este artigo
    • Ele aborda problemas que, alguns anos atrás, precisavam ser resolvidos manualmente
    • Agradecimentos ao autor
  • Pergunta sobre um sistema FOSS de analytics

    • Estou criando um sistema FOSS de analytics fácil de instalar
    • Quero enviar os dados de eventos para um banco SQLite separado, para isolá-los dos dados do app principal
    • Tenho preocupação com a escalabilidade para lidar com mais de 1000 eventos por segundo
    • Estou considerando armazenar os eventos na memória do servidor e gravá-los em lote uma vez por segundo
    • Gostaria de saber se isso é uma forma razoável de resolver muitos dos problemas de escrita em banco no SQLite
  • Problema de GVL na gem sqlite3-ruby

    • A gem sqlite3-ruby não libera o GVL durante chamadas ao SQLite
    • Na maior parte dos casos, isso parece uma decisão razoável
    • É possível que extensões em Python tenham sido projetadas de outra forma
    • A gem extralite libera o GVL durante bloqueios, geralmente é mais rápida e não tem problemas de concorrência
  • Configuração de um serviço web pessoal

    • Algumas configurações usadas em um serviço web pessoal:
      • PRAGMA journal_mode = WAL
      • PRAGMA busy_timeout = 5000
      • PRAGMA synchronous = NORMAL
      • PRAGMA cache_size = 1000000000
      • PRAGMA foreign_keys = true
      • PRAGMA temp_store = memory
      • uso de transações BEGIN IMMEDIATE
  • Pergunta sobre Django

    • Este artigo é excelente
    • Fico curioso se existe alguma solução parecida para Django
    • O ArchiveBox usa SQLite por meio do Django e frequentemente enfrenta os problemas mencionados no caso de Rails
    • Seria ótimo se existisse uma solução em nível de camada SQLite que não exigisse serializar todas as escritas por outros canais do app
  • Dúvida sobre a configuração padrão de busy_timeout

    • O artigo é muito informativo e bem escrito
    • Fico curioso por que o método padrão de busy_timeout tem um atraso que penaliza consultas mais antigas
    • Também queria entender por que isso faz sentido como configuração padrão
  • Opinião sobre usar SQLite com Rails

    • Gosto de SQLite e de Rails, mas isso parece semelhante a usar MS Access em produção
  • Agradecimento por resolver problemas de integração com Rails

    • Fico sempre feliz em ver alguém resolver problemas de integração e ajudar outras pessoas
    • Espero que essas correções sejam incluídas na configuração padrão do Rails
    • Administro apps em Rails e, alguns anos atrás, migrei para Postgres, com ótimo resultado
    • Ainda assim, é bom ter alternativas, e uso SQLite em outros trabalhos