205 votes

accès simultané à sqlite3

SQLite gère-t-il de manière sûre les accès simultanés par de multiples processus qui lisent/écrivent à partir d'une même base de données ? Y a-t-il des exceptions à cette règle ?

5 votes

J'ai oublié de mentionner le prime goall : la plupart des réponses disent que c'est bon : "mais, à mon avis, ne répondent pas en détail / n'expliquent pas clairement ce qui se passe si deux opérations d'écriture arrivent exactement au même moment (cas théorique très rare). 1) Est-ce que cela déclencherait une erreur et interromprait le programme ? ou 2) Est-ce que la deuxième opération d'écriture attendrait que la première soit terminée ? ou 3) Est-ce que l'une des opérations d'écriture serait abandonnée (perte de données !)? 4) Autre chose ? Connaître les limites de l'écriture simultanée peut être utile dans de nombreuses situations.

7 votes

@Basj En bref,2)il attendra et réessayera plusieurs fois(configurable),1)déclenchera une erreur,SQLITE_BUSY.3)vous pouvez enregistrer un Callback pour gérer les erreurs SQLITE_BUSY.

128voto

kijin Points 4609

Si la plupart de ces accès concurrents sont des lectures (par exemple SELECT), SQLite peut très bien les gérer. Mais si vous commencez à écrire simultanément, la contention des verrous peut devenir un problème. Beaucoup dépendrait alors de la vitesse de votre système de fichiers, puisque le moteur SQLite lui-même est extrêmement rapide et possède de nombreuses optimisations intelligentes pour minimiser la contention. Surtout SQLite 3.

Pour la plupart des applications de bureau/portable/tablette/téléphone, SQLite est assez rapide car il n'y a pas assez de concurrence. (Firefox utilise abondamment SQLite pour les signets, l'historique, etc.)

Pour les applications serveur, quelqu'un a dit il y a quelque temps que tout ce qui était inférieur à 100K pages vues par jour pouvait être parfaitement géré par une base de données SQLite dans des scénarios typiques (par ex. blogs, forums), et je n'ai encore vu aucune preuve du contraire. En fait, avec les disques et processeurs modernes, 95% des sites et services web fonctionneraient parfaitement avec SQLite.

Si vous voulez un accès très rapide en lecture/écriture, utilisez une base de données SQLite en mémoire. La mémoire vive est plus rapide de plusieurs ordres de grandeur que le disque.

31 votes

Le PO ne pose pas de question sur l'efficacité et la vitesse, mais sur l'accès simultané. Les serveurs Web n'ont rien à voir avec cela. Idem pour les bases de données en mémoire.

3 votes

Vous avez raison dans une certaine mesure, mais l'efficacité et la rapidité jouent un rôle. Des accès plus rapides signifient que le temps d'attente des verrous est plus faible, ce qui réduit les inconvénients des performances de SQLite en matière de concurrence. En particulier, si vous avez peu d'écritures rapides, la base de données ne semblera pas du tout avoir de problèmes de concurrence pour un utilisateur.

1 votes

Comment gérer l'accès simultané à une base de données sqlite en mémoire ?

56voto

ffeast Points 6645

Oui, c'est le cas. Essayons de comprendre pourquoi

SQLite est transactionnel

Toutes les modifications au sein d'une même transaction dans SQLite se produisent soit complètement ou pas du tout

Cette prise en charge ACID ainsi que les lectures/écritures simultanées sont assurées de deux manières - en utilisant la méthode dite de "l'ACID". journal intime (appelons-le " ancienne méthode ") ou enregistrement à l'avance (appelons-le " nouvelle façon ")

Journal (ancienne méthode)

Dans ce mode, SQLite utilise AU NIVEAU DE LA BASE DE DONNÉES verrouillage . C'est le point crucial à comprendre.

Cela signifie qu'à chaque fois qu'il a besoin de lire/écrire quelque chose, il acquiert d'abord un verrou sur l'objet de l'utilisateur. ENTIRE fichier de base de données. Plusieurs lecteurs peuvent coexister et lire quelque chose en parallèle.

Pendant l'écriture, elle s'assure qu'un verrou exclusif est acquis et aucun autre est en train de lire/écrire simultanément et donc les écritures sont sûres.

C'est pourquoi aquí ils disent que SQlite implémente sérialisable transactions

Troubles

Comme il doit verrouiller une base de données entière à chaque fois et que tout le monde attend qu'un processus traite l'écriture, la concurrence est affectée et de telles écritures/lectures simultanées ont des performances assez faibles.

Retours et interruptions de service

Avant d'écrire quelque chose dans le fichier de la base de données, SQLite enregistre d'abord le morceau à 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ère ce fichier temporaire et rétablit les changements à partir de celui-ci.

Journalisation en écriture anticipée ou WAL (nouvelle méthode)

Dans ce cas, toutes les écritures sont ajoutées à un fichier temporaire ( journal d'anticipation ) et ce fichier est périodiquement fusionné avec la base de données originale. Lorsque SQLite cherche quelque chose, il vérifie d'abord ce fichier temporaire et si rien n'est trouvé, il continue avec le fichier principal de la base de données.

Par conséquent, les lecteurs ne sont pas en concurrence avec les rédacteurs et les performances sont bien meilleures par rapport à l'ancienne méthode.

Mises en garde

SQlite dépend fortement de la fonctionnalité de verrouillage du système de fichiers sous-jacent, il doit donc être utilisé avec précaution, plus de détails aquí

Vous êtes également susceptible de rencontrer le la base de données est verrouillée erreur, en particulier en mode journalisé. Votre application doit donc être conçue en tenant compte de cette erreur.

44voto

vcsjones Points 51910

Oui, SQLite gère bien la concurrence, mais il n'est pas le meilleur du point de vue des performances. D'après ce que je peux dire, il n'y a pas d'exception à cela. Les détails sont sur le site de SQLite : http://www.sqlite.org/lockingv3.html

Cette déclaration est intéressante : "Le module pager s'assure que les changements se produisent tous en même temps, que tous les changements se produisent ou qu'aucun ne se produise, que deux processus ou plus n'essaient pas d'accéder à la base de données de manière incompatible au même moment".

2 votes

Voici quelques commentaires sur les problèmes rencontrés sur différentes plateformes Il s'agit des systèmes de fichiers NFS et de Windows (bien que cela ne concerne que les anciennes versions de Windows...).

2 votes

Est-il possible de charger une base de données SQLite3 en RAM pour l'utiliser pour tous les utilisateurs en PHP ? Je pense que non, car il s'agit d'un langage procédural.

1 votes

@foxyfennec un point de départ, bien que SQLite ne soit pas forcément la base de données optimale pour ce cas d'utilisation. sqlite.org/inmemorydb.html

37voto

akc42 Points 806

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 maintenir 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, ce qu'il fait lorsque la dernière connexion à la base de données se ferme. Dans le cas d'un site très actif, la fermeture de toutes les connexions peut prendre quelques secondes, mais 100 000 visites par jour ne devraient pas poser de problème.

0 votes

Intéressant, mais ne fonctionne que sur une seule machine, pas sur des scénarios où la base de données est accessible sur tout le réseau.

1 votes

Il convient de noter que le délai d'attente par défaut pour un rédacteur est de 5 secondes et qu'après ce délai, le rédacteur doit attendre. database is locked l'erreur sera levée par le rédacteur

18voto

obgnaw Points 2489

SQLite possède un verrouillage lecteurs-écrivains au niveau de la base de données. Plusieurs connexions (appartenant éventuellement à des processus différents) 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 supporte un nombre illimité de lecteurs simultanés, mais ne permet qu'un seul écrivain à un moment donné. Dans de nombreuses situations, ce n'est pas un problème. Mise en file d'attente des scripteurs. Chaque application fait son travail de base de données rapidement et passe à autre chose, et aucun verrou ne dure plus de quelques dizaines de millisecondes. Mais il y a des applications qui nécessitent plus de concurrence, et ces applications peuvent avoir besoin de chercher une solution différente. -- Utilisations appropriées de SQLite @ SQLite.org

Le verrou lecteur-écrivain permet un traitement indépendant des transactions et il est mis en œuvre à 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 n'effectue une opération d'écriture sur une base de données. Après l'obtention du verrou exclusif, les opérations de lecture et d'écriture des autres connexions sont bloquées jusqu'à ce que le verrou soit libéré.

Détails d'implémentation pour le cas des écritures simultanées

SQLite dispose d'une table de verrouillage qui permet de verrouiller la base de données le plus tard possible lors d'une opération d'écriture afin de garantir une concurrence maximale.

L'état initial est UNLOCKED, 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 que même une transaction a été lancée avec BEGIN, la connexion est toujours dans l'état UNLOCKED.

Après l'état UNLOCKED, l'état suivant est l'état SHARED. Pour pouvoir lire (et non écrire) des données dans la base de données, la connexion doit d'abord passer à 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 des données de la même base de données en même temps. Mais tant qu'un seul verrou SHARED n'est pas libéré, aucune connexion ne peut mener à bien 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 RESERVÉ.

Un seul verrou RESERVED peut être actif à la fois, mais plusieurs verrous SHARED peuvent coexister avec un seul verrou RESERVED. RESERVED diffère de PENDING en ce que de nouveaux verrous SHARED peuvent être acquis tant qu'il y a un verrou RESERVED. -- Verrouillage de fichiers et concurrence dans SQLite Version 3 @ SQLite.org

Une fois qu'une connexion obtient un verrou RESERVÉ, 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 le tampon, plutôt que d'être réellement écrites sur le disque. Les modifications apportées au contenu de la lecture sont enregistrées dans le tampon de mémoire. Lorsqu'une connexion veut soumettre une modification (ou une transaction), il est nécessaire de transformer le verrou RESERVED en verrou EXCLUSIVE. Pour obtenir le verrou, il faut d'abord lever le verrou vers un verrou PENDING.

Un verrou PENDING signifie que le processus qui détient le verrou veut écrire dans la base de données dès que possible et attend simplement que tous les verrous SHARED actuels soient levés pour pouvoir obtenir un verrou EXCLUSIVE. Aucun nouveau verrou SHARED n'est autorisé sur la base de données si un verrou PENDING est actif, mais les verrous SHARED existants peuvent continuer.

Un verrou EXCLUSIF est nécessaire pour pouvoir écrire dans le fichier de la base de données. Un seul verrou EXCLUSIF est autorisé sur le fichier et aucun autre verrou de quelque nature que ce soit ne peut coexister avec un verrou EXCLUSIF. Afin de maximiser la concurrence, SQLite s'efforce de minimiser le temps pendant lequel les verrous EXCLUSIFS sont maintenus. -- Verrouillage de fichiers et concurrence dans SQLite Version 3 @ SQLite.org

On pourrait donc dire que SQLite ne gère pas les accès concurrents de plusieurs processus écrivant dans la même base de données simplement parce qu'il ne le supporte pas ! Vous obtiendrez SQLITE_BUSY o SQLITE_LOCKED pour le second auteur lorsqu'il atteint la limite de réessai.

0 votes

Merci. Un exemple de code avec 2 rédacteurs serait super génial pour comprendre comment ça marche.

2 votes

@Basj en bref, sqlite a un verrou de lecture-écriture sur le fichier de base de données, c'est la même chose que l'écriture simultanée d'un fichier. Avec WAL, il n'est toujours pas possible d'écrire en même temps, mais WAL peut accélérer l'écriture, et la lecture et l'écriture peuvent être simultanées.

2 votes

Pourriez-vous utiliser une file d'attente et avoir plusieurs threads qui alimentent la file d'attente et un seul thread qui écrit dans la base de données en utilisant les instructions SQL dans la file d'attente. Quelque chose comme este

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X