SQLite3 gère-t-il en toute sécurité l'accès simultané par plusieurs processus lisant / écrivant à partir de la même base de données? Y a-t-il des exceptions de plate-forme à cela?
SQLite3 gère-t-il en toute sécurité l'accès simultané par plusieurs processus lisant / écrivant à partir de la même base de données? Y a-t-il des exceptions de plate-forme à cela?
Réponses:
Si la plupart de ces accès simultanés sont des lectures (par exemple SELECT), SQLite peut très bien les gérer. Mais si vous commencez à écrire simultanément, les conflits de verrouillage peuvent devenir un problème. Beaucoup dépendrait alors de la vitesse de votre système de fichiers, car le moteur SQLite lui-même est extrêmement rapide et dispose de nombreuses optimisations intelligentes pour minimiser les conflits. Surtout SQLite 3.
Pour la plupart des applications de bureau / ordinateur portable / tablette / téléphone, SQLite est assez rapide car il n'y a pas assez de concurrence. (Firefox utilise largement SQLite pour les signets, l'historique, etc.)
Pour les applications serveur, quelqu'un a dit il y a quelque temps que moins de 100K pages vues par jour pouvaient être parfaitement gérées par une base de données SQLite dans des scénarios typiques (par exemple, des blogs, des forums), et je n'ai pas encore vu de preuves du contraire. En fait, avec les disques et les processeurs modernes, 95% des sites Web et des services Web fonctionneraient parfaitement avec SQLite.
Si vous voulez un accès en lecture / écriture très rapide, utilisez une base de données SQLite en mémoire . La RAM est de plusieurs ordres de grandeur plus rapide que le disque.
Oui, SQLite gère bien la concurrence, mais ce n'est pas le meilleur du point de vue des performances. D'après ce que je peux dire, il n'y a aucune exception à cela. Les détails sont sur le site de SQLite: https://www.sqlite.org/lockingv3.html
Cette déclaration est intéressante: "Le module de téléavertisseur s'assure que les modifications se produisent en une seule fois, que toutes les modifications se produisent ou qu'aucune d'entre elles ne se produisent, que deux processus ou plus n'essaient pas d'accéder à la base de données de manière incompatible en même temps"
Oui. Voyons pourquoi
Toutes les modifications au sein d'une même transaction dans SQLite se produisent complètement ou pas du tout
Un tel support ACID ainsi que des lectures / écritures simultanées sont fournis de 2 manières - en utilisant la soi-disant journalisation (appelons-la « ancienne méthode ») ou la journalisation en écriture anticipée (appelons-la « nouvelle manière »)
Dans ce mode, SQLite utilise le verrouillage DATABASE-LEVEL . C'est le point crucial à comprendre.
Cela signifie que chaque fois qu'il a besoin de lire / écrire quelque chose, il acquiert d'abord un verrou sur le fichier de base de données ENTIER . Plusieurs lecteurs peuvent coexister et lire quelque chose en parallèle
Pendant l'écriture, il s'assure qu'un verrou exclusif est acquis et qu'aucun autre processus ne lit / écrit simultanément et que les écritures sont donc sûres.
C'est pourquoi ici ils disent que SQlite implémente des transactions sérialisables
Comme il doit verrouiller une base de données entière à chaque fois et que tout le monde attend un processus de gestion de l'écriture, la concurrence en souffre et ces écritures / lectures simultanées sont de performances assez faibles
Avant d'écrire quelque chose dans le fichier de base de données, SQLite enregistre d'abord le bloc à modifier dans un fichier temporaire. Si quelque chose se bloque au milieu de l'écriture dans le fichier de base de données, il récupérera ce fichier temporaire et annulera les modifications.
Dans ce cas, toutes les écritures sont ajoutées à un fichier temporaire ( journal des écritures anticipées ) et ce fichier est périodiquement fusionné avec la base de données d'origine. Lorsque SQLite recherche quelque chose, il vérifie d'abord ce fichier temporaire et si rien n'est trouvé, continuez avec le fichier de base de données principal.
En conséquence, les lecteurs ne sont pas en concurrence avec les écrivains et les performances sont bien meilleures par rapport à l'ancienne.
SQlite dépend fortement de la fonctionnalité de verrouillage du système de fichiers sous-jacent, il doit donc être utilisé avec prudence, plus de détails ici
Vous êtes également susceptible de rencontrer une erreur de verrouillage de la base de données , en particulier en mode journalisé, votre application doit donc être conçue avec cette erreur à l'esprit.
Personne ne semble avoir mentionné le mode WAL (Write Ahead Log). Assurez-vous que les transactions sont correctement organisées et avec le mode WAL activé, il n'est pas nécessaire de garder la base de données verrouillée pendant que les gens lisent des choses pendant qu'une mise à jour est en cours.
Le seul problème est qu'à un moment donné, le WAL doit être réincorporé dans la base de données principale, et il le fait lorsque la dernière connexion à la base de données se ferme. Avec un site très occupé, vous constaterez peut-être que la fermeture de toutes les connexions prend quelques secondes, mais 100 000 visites par jour ne devraient pas être un problème.
database is locked
erreur sera levée par l'auteur
En 2019, deux nouvelles options d'écriture simultanée ne sont pas encore publiées mais disponibles dans des succursales distinctes.
L'avantage de ce mode journal par rapport au mode "wal" normal est que les rédacteurs peuvent continuer à écrire dans un fichier wal pendant que l'autre est contrôlé.
BEGIN CONCURRENT - lien vers la documentation détaillée
L'amélioration BEGIN CONCURRENT permet à plusieurs rédacteurs de traiter simultanément les transactions d'écriture si la base de données est en mode «wal» ou «wal2», bien que le système sérialise toujours les commandes COMMIT.
Lorsqu'une transaction d'écriture est ouverte avec "BEGIN CONCURRENT", le verrouillage réel de la base de données est différé jusqu'à ce qu'un COMMIT soit exécuté. Cela signifie que n'importe quel nombre de transactions démarrées avec BEGIN CONCURRENT peut se dérouler simultanément. Le système utilise un verrouillage optimiste au niveau de la page pour empêcher la validation de transactions simultanées conflictuelles.
Ensemble, ils sont présents dans begin-concurrent-wal2 ou chacun dans une branche distincte .
begin concurrent
truc.
SQLite a un verrou de lecture-écriture au niveau de la base de données. Plusieurs connexions (possiblement détenues par différents processus) peuvent lire les données de la même base de données en même temps, mais une seule peut écrire dans la base de données.
SQLite prend en charge un nombre illimité de lecteurs simultanés, mais il n'autorisera qu'un seul écrivain à tout instant dans le temps. Dans de nombreuses situations, ce n'est pas un problème. Écrivain file d'attente. Chaque application fait son travail de base de données rapidement et évolue, et aucun verrou ne dure plus de quelques dizaines de millisecondes. Mais certaines applications nécessitent plus de concurrence et ces applications peuvent avoir besoin de rechercher une solution différente. - Utilisations appropriées pour SQLite @ SQLite.org
Le verrou lecteurs-rédacteurs permet un traitement indépendant des transactions et est implémenté à l'aide de verrous exclusifs et partagés au niveau de la base de données.
Un verrou exclusif doit être obtenu avant qu'une connexion effectue une opération d'écriture sur une base de données. Une fois le verrou exclusif obtenu, les opérations de lecture et d'écriture à partir d'autres connexions sont bloquées jusqu'à ce que le verrou soit à nouveau libéré.
SQLite a une table de verrouillage qui permet de verrouiller la base de données le plus tard possible lors d'une opération d'écriture pour assurer une concurrence maximale.
L'état initial est DÉVERROUILLÉ et, dans cet état, la connexion n'a pas encore accédé à la base de données. Lorsqu'un processus est connecté à une base de données et même qu'une transaction a été lancée avec BEGIN, la connexion est toujours à l'état DÉVERROUILLÉ.
Après l'état UNLOCKED, l'état suivant est l'état SHARED. Afin de pouvoir lire (et non écrire) les données de la base de données, la connexion doit d'abord entrer dans l'état SHARED, en obtenant un verrou SHARED. Plusieurs connexions peuvent obtenir et maintenir des verrous SHARED en même temps, de sorte que plusieurs connexions peuvent lire les données de la même base de données en même temps. Mais tant que même un seul verrou SHARED n'est pas libéré, aucune connexion ne peut réussir une écriture dans la base de données.
Si une connexion veut écrire dans la base de données, elle doit d'abord obtenir un verrou RÉSERVÉ.
Un seul verrou RÉSERVÉ peut être actif à la fois, bien que plusieurs verrous PARTAGÉS puissent coexister avec un seul verrou RÉSERVÉ. RESERVED diffère de PENDING en ce que de nouvelles serrures PARTAGÉES peuvent être acquises pendant qu'il y a une serrure RESERVED. - Verrouillage de fichiers et concurrence dans SQLite Version 3 @ SQLite.org
Une fois qu'une connexion obtient un verrou RÉSERVÉ, elle peut commencer à traiter les opérations de modification de la base de données, bien que ces modifications ne puissent être effectuées que dans la mémoire tampon, plutôt que réellement écrites sur le disque. Les modifications apportées au contenu de lecture sont enregistrées dans la mémoire tampon. Lorsqu'une connexion souhaite soumettre une modification (ou une transaction), il est nécessaire de mettre à niveau le verrou RÉSERVÉ vers un verrou EXCLUSIF. Pour obtenir la serrure, vous devez d'abord soulever la serrure jusqu'à une serrure PENDING.
Un verrou EN ATTENTE signifie que le processus qui détient le verrou veut écrire dans la base de données dès que possible et attend juste que tous les verrous SHARED actuels soient effacés afin de pouvoir obtenir un verrou EXCLUSIF. Aucun nouveau verrou SHARED n'est autorisé sur la base de données si un verrou PENDING est actif, bien que les verrous SHARED existants soient autorisés à continuer.
Un verrou EXCLUSIF est nécessaire pour écrire dans le fichier de base de données. Un seul verrou EXCLUSIF est autorisé sur le fichier et aucun autre verrou de quelque type que ce soit n'est autorisé à coexister avec un verrou EXCLUSIF. Afin de maximiser la concurrence, SQLite s'efforce de minimiser la durée pendant laquelle les verrous EXCLUSIFS sont maintenus. - Verrouillage de fichiers et concurrence dans SQLite Version 3 @ SQLite.org
Vous pourriez donc dire que SQLite gère en toute sécurité l'accès simultané par plusieurs processus écrivant dans la même base de données simplement parce qu'il ne le prend pas en charge! Vous obtiendrez SQLITE_BUSY
ou SQLITE_LOCKED
pour le deuxième rédacteur lorsqu'il atteindra la limite de relance.
Ce fil est vieux mais je pense qu'il serait bon de partager le résultat de mes tests effectués sur sqlite: j'ai exécuté 2 instances de programme python (différents processus même programme) exécutant des instructions SELECT et UPDATE commandes sql dans une transaction avec verrouillage EXCLUSIF et délai d'expiration défini sur 10 secondes pour obtenir un verrou et le résultat était frustrant. Chaque instance a fait une boucle de 10000 pas:
Même si sqlite accordait un verrouillage exclusif sur la transaction, le nombre total de cycles réellement exécutés n'était pas égal à 20 000 mais inférieur (nombre total d'itérations sur un seul compteur compté pour les deux processus). Le programme Python n'a presque pas levé une seule exception (une seule fois lors de la sélection pour 20 exécutions). La révision de sqlite au moment du test était 3.6.20 et python v3.3 CentOS 6.5. À mon avis, il est préférable de trouver un produit plus fiable pour ce type de travail ou de restreindre les écritures sur sqlite à un seul processus / thread unique.
with con
c'est suffisant.