1 points par GN⁺ 2024-09-13 | 1 commentaires | Partager sur WhatsApp
  • Au cours de l’année écoulée, l’auteur s’est efforcé de comprendre en profondeur comment exécuter des applications Rails avec SQLite de manière performante et stable
  • Il a tiré plusieurs enseignements de ce travail et souhaite les partager
  • L’article explique les causes des problèmes et les moyens de les résoudre

Les problèmes de SQLite avec Rails

  • Par défaut, une application Rails utilisant SQLite n’est pas prête à l’emploi
  • Avec quelques ajustements et réglages fins, il est possible d’obtenir une application performante et stable
  • Avec Rails 8, l’objectif est d’atteindre un niveau prêt pour la production avec la configuration par défaut

Application de démonstration « Lorem News »

  • L’article s’appuie sur une application de démonstration appelée « Lorem News » pour expliquer les problèmes et leurs solutions
  • Cette application est un clone de Hacker News, dans lequel les utilisateurs peuvent publier des billets et des commentaires

Tests de performance

  • Les performances sont testées avec le CLI de load testing oha et une route de benchmarking intégrée à l’application
  • Les mesures sont effectuées à la fois sur des requêtes uniques et des requêtes concurrentes

Problème principal : exceptions SQLITE_BUSY

  • SQLite utilise un verrou d’écriture afin de n’autoriser qu’une seule opération d’écriture à la fois
  • Lorsque plusieurs connexions tentent simultanément d’obtenir ce verrou d’écriture, des exceptions SQLITE_BUSY se produisent
  • Pour résoudre ce problème, il faut utiliser des transactions immédiates

Transactions immédiates

  • Par défaut, SQLite utilise le mode de transaction différée
  • Avec des transactions immédiates, la tentative d’acquérir le verrou d’écriture se fait immédiatement, et un nouvel essai est possible en cas d’échec
  • Le gem sqlite3-ruby permet de définir le mode de transaction par défaut sur le mode immédiat

Configuration du délai d’attente

  • Un réglage de délai d’attente dans le fichier database.yml permet de réduire les exceptions SQLITE_BUSY
  • Le paramètre busy_timeout de SQLite permet de réessayer l’obtention du verrou d’écriture

Problème du GVL (Global VM Lock)

  • Le gem sqlite3-ruby ne libère pas le GVL lorsqu’il appelle le code C de SQLite
  • Cela dégrade les performances en situation de concurrence
  • L’utilisation de busy_handler permet de libérer le GVL et d’améliorer les performances

Réimplémentation de busy_timeout

  • busy_timeout est réimplémenté afin que toutes les requêtes soient réessayées à la même fréquence
  • Cela évite que les requêtes les plus anciennes n’atteignent le délai d’expiration

Améliorations des performances

  • Pour améliorer les performances, il faut appliquer les réglages suivants
    • utiliser des transactions immédiates
    • configurer un délai d’attente
    • utiliser busy_handler
    • utiliser le mode WAL (Write-Ahead Logging)
    • séparer les pools de connexions en lecture et en écriture

Résumé de GN⁺

  • L’article traite des problèmes de performances des applications Rails utilisant SQLite et de leurs solutions
  • Les performances peuvent être améliorées grâce aux transactions immédiates, à la configuration du délai d’attente, à la libération du GVL, à l’utilisation du mode WAL et à la séparation des pools de connexions en lecture et en écriture
  • Cet article sera très utile aux développeurs qui utilisent SQLite et Rails
  • Parmi les autres projets offrant des fonctionnalités similaires, PostgreSQL et MySQL sont recommandés

1 commentaires

 
GN⁺ 2024-09-13
Commentaires sur Hacker News
  • Présentation du projet Litestack par Oldmoe

    • Les personnes qui utilisent SQLite et Rails devraient jeter un œil au projet Litestack d’Oldmoe
    • Litestack est une gem Ruby qui fournit une infrastructure de données pour applications web en tirant parti de la puissance de SQLite
    • Il fournit dans un seul package une base de données SQL, un cache rapide, une file de tâches robuste, un broker de messages fiable, un moteur de recherche plein texte et une plateforme de métriques
    • Je l’utilise actuellement sur un projet et j’en suis très satisfait
  • Merci pour cet article détaillé

    • C’est une information utile pour celles et ceux qui cherchent à faire monter en charge des applications web SQLite
    • Cela peut aussi s’appliquer à d’autres frameworks au-delà de Rails
    • Merci à l’auteur
  • Recommandé à toute personne travaillant avec SQLite

    • Quel que soit le langage ou le framework utilisé, toute personne travaillant avec SQLite devrait lire cet article
    • Il traite de problèmes qu’il fallait résoudre soi-même il y a quelques années
    • Merci à l’auteur
  • Question sur un système d’analyse FOSS

    • Je construis un système d’analyse FOSS facile à installer
    • J’essaie d’envoyer les données d’événements vers une base SQLite séparée afin de les isoler des données de l’application principale
    • J’ai des inquiétudes sur la montée en charge au-delà de 1000 événements par seconde
    • J’envisage de stocker les événements en mémoire sur le serveur puis de les écrire en lot une fois par seconde
    • J’aimerais savoir si c’est une manière raisonnable de résoudre le problème des nombreuses écritures en base avec SQLite
  • Le problème de GVL dans la gem sqlite3-ruby

    • La gem sqlite3-ruby ne libère pas la GVL lors des appels à SQLite
    • Cela semble être une décision raisonnable dans la plupart des cas
    • Les extensions Python ont peut-être été conçues différemment
    • La gem extralite libère la GVL pendant les opérations bloquantes, est généralement plus rapide et n’a pas de problèmes de concurrence
  • Configuration d’un service web personnel

    • Quelques réglages utilisés sur un service web personnel :
      • PRAGMA journal_mode = WAL
      • PRAGMA busy_timeout = 5000
      • PRAGMA synchronous = NORMAL
      • PRAGMA cache_size = 1000000000
      • PRAGMA foreign_keys = true
      • PRAGMA temp_store = memory
      • utilisation de transactions BEGIN IMMEDIATE
  • Question à propos de Django

    • Cet article est excellent
    • Je me demande s’il existe une solution similaire pour Django
    • ArchiveBox utilise SQLite via Django et rencontre souvent les problèmes mentionnés côté Rails
    • Ce serait bien d’avoir une solution au niveau de la couche SQLite qui ne sérialise pas toutes les écritures via d’autres canaux de l’application
  • Interrogation sur la configuration par défaut de busy_timeout

    • C’est un article très instructif et bien écrit
    • Je me demande pourquoi la méthode busy_timeout par défaut introduit une latence qui pénalise les requêtes anciennes
    • Je me demande pourquoi cela a du sens comme réglage par défaut
  • Avis sur l’utilisation de SQLite avec Rails

    • J’aime SQLite et Rails, mais cela ressemble à utiliser MS Access en production
  • Merci pour la résolution des problèmes d’intégration avec Rails

    • Je suis toujours heureux de voir des gens résoudre des problèmes d’intégration et aider les autres
    • J’aimerais que ces correctifs soient inclus dans la configuration par défaut de Rails
    • J’exploite une application Rails et je suis passé à Postgres il y a quelques années, avec une très grande satisfaction
    • C’est bien qu’il existe encore des alternatives, et j’utilise SQLite pour d’autres tâches