8
votes

SQLite3 et multiprocession

J'ai remarqué que SQLite3 n'est pas vraiment capable ni fiable lorsque je l'utilise à l'intérieur d'un environnement multiprofessionnel. Chaque processus essaie d'écrire des données dans la même base de données, de sorte qu'une connexion est utilisée par plusieurs threads. Je l'ai essayé avec le check_same_thread = False option, mais le nombre d'insertions est assez aléatoire: parfois, cela inclut tout, parfois pas. Devrais-je paralliser uniquement des parties de la fonction (récupérer des données de la bande), empiler leurs sorties dans une liste et les mettre dans la table toutes ensemble ou y a-t-il un moyen fiable de gérer plusieurs connexions avec SQLite?


1 commentaires

Il serait bon de savoir ce que les paramètres de pragma que vous aviez sur ce dB ...


4 Réponses :


9
votes

Tout d'abord, il existe une différence entre le multitraitement (processus multiples) et la multithreading (threads multiples dans un processus).

Il semble que vous parlez de multithreading ici. Il y a quelques mises en garde à prendre conscience de l'utilisation de SQLite dans un environnement multithread. Documentation SQLite mentionne les éléments suivants:

  • n'utilise pas la même connexion de base de données en même temps dans plus de un fil.
  • sur certains systèmes d'exploitation, une connexion de base de données devrait toujours être utilisé dans le même fil dans lequel il a été créé à l'origine.

    voir ici pour une information plus détaillée: est SQLite Thread-Safe?


4 commentaires

Et pour ajouter à cela, SQLITE fonctionne bien dans un environnement multi-processus, tant que vous savez que le verrouillage peut entraîner des appels à des appels (échec) et qu'ils doivent ensuite être réessayés.


Je connais le fil / processus -Différence, et j'utilise plusieurs processus (module multiprofessionnel avec piscines). Je pense que les problèmes sont les serrures DB, mais il n'y a pas de message d'erreur généré dans les processus (en général, mes processus ne se soucient pas des erreurs, ils semblent simplement les transmettre) ...


Vous devez également être conscient que si vous accrochez les processus sur plusieurs systèmes, vous allez avoir tout le plaisir du verrouillage du fichier sur des systèmes en réseau. C'est une zone difficile; Vraiment Il est préférable de garder le nombre de processus suffisamment petits pour avoir sur un seul système.


@ADEWREWCOOKE Avez-vous un exemple de SQLite dans un environnement multi-processus? Voulez-vous dire qu'il y a un moyen d'envoyer par exemple Un objet de curseur à un processus d'enfant? Ou les processus enfants devraient-ils créer leurs propres curseurs?



0
votes

Si je devais construire un système comme celui que vous décrivez, en utilisant SQLite, je commencerais par écrire un serveur async (à l'aide du module asynchat ) pour gérer toute l'accès à la base de données SQLITE, Et puis j'écrirais les autres processus pour utiliser ce serveur. Lorsqu'il n'y a qu'un seul processus accédant directement au fichier dB, il peut appliquer une séquence stricte de requêtes afin que deux processus ne soient pas en train de marcher sur les orteils. Il est également plus rapide que d'ouverture et de fermeture continue de la DB.

En fait, j'essaierais également d'éviter de maintenir des sessions, en d'autres termes, j'essaierais d'écrire tous les autres processus afin que chaque transaction de base de données soit indépendante. Au minimum, cela signifierait permettre une transaction de contenir une liste des instructions SQL, pas seulement une seule, et elle pourrait même nécessiter une capacité si de sorte que vous puissiez sélectionner un enregistrement, vérifier qu'un champ est égal. à x, et seulement alors, mettez à jour ce champ. Si votre application existante ferme la base de données après chaque transaction, vous n'avez pas besoin de vous inquiéter des sessions.

Vous pourrez peut-être utiliser quelque chose comme Nosqlite http://code.google.com/p/ nosqlite /


1 commentaires

Je n'ai pas reçu la deuxième partie ... dans mon paramètre actuel, chaque processus relie la base de données, exécute un insertion, commet-la et ferme la connexion ..Vous voulez dire cela?



2
votes

sqlidification : une enveloppe légère autour de la base de données SQLITE3 de Python, avec une interface de type dict et plusieurs Support d'accès -Tthread.


1 commentaires

Le support multi-thread signifie ici ne casse pas votre code car SQLite ne jette pas l'exception ProgrammingError. Cependant, de la part de la LIB DOC -> "Le support multithreadé ne vous donne aucun avantage de performance." ( PYPI.PYTHON.ORG/PYPI/SQLITITEDICT )



8
votes

Je viens de travailler sur quelque chose de très similaire:

  • Processus multiples (pour moi un pool de traitement de 4 à 32 travailleurs)
  • Chaque travailleur de processus fait des choses qui incluent obtenir des informations du Web (un appel à l'API d'Alchemy pour la mienne)
  • Chaque processus ouvre sa propre connexion SQLite3, tout au seul fichier, et chacun processus ajoute une entrée avant d'obtenir la prochaine tâche de la pile

    Au début, je pensais que je voyais le même problème que vous, puis je l'ai retrouvé à des problèmes qui se chevauchent et en contradiction avec la récupération des informations du Web. Depuis que j'avais raison là-bas, j'ai fait des tests de torture sur SQLite et Multiprocessing et que je pouvais organiser de nombreux travailleurs de processus, tous connectés et ajoutes au même fichier SQLite sans coordination et il s'agissait de rock solide lorsque je faisais simplement des données de test.

    Alors maintenant, je regarde votre phrase "(récupérer des données du Web)" - Vous pourriez peut-être essayer de remplacer ces données de récupération avec quelques données factices afin de vous assurer que c'est vraiment la connexion SQLITE3 vous causant des problèmes. Au moins dans mon étui testé (en cours d'exécution en ce moment dans une autre fenêtre), j'ai constaté que plusieurs processus ont été capables de contribuer à toutes leur propre connexion sans problèmes, mais votre description correspond exactement au problème que je dispose lorsque deux processus se mettent sur l'autre en allant Pour l'API Web (erreur très étrange effectivement) et parfois, n'obtenez pas les données attendues, ce qui laisse bien sûr une fente vide dans la base de données. Ma solution éventuelle consistait à détecter cette défaillance au sein de chaque travailleur et à réessayer l'appel de l'API Web à ce moment-là (aurait pu être plus élégante, mais c'était pour un piratage personnel).

    Mes excuses Si cela ne s'applique pas à votre cas, sans code, il est difficile de savoir ce que vous faites face, mais la description me fait me demander si vous voulez élargir vos considérations.


0 commentaires