2009-05-18 6 views
4

Je suis en train d'exécuter un certain nombre de threads qui tentent chacun d'effectuer des INSERTS dans une base de données SQLite. Chaque thread crée sa propre connexion à la base de données. Ils créent chacun une commande, ouvrent une transaction et exécutent des INSERTS puis clôturent la transaction. Il semble que le deuxième thread à tenter n'importe quoi obtient l'exception SQLiteException suivante: Le fichier de base de données est verrouillé. J'ai essayé de déballer les INSERTS de la transaction et de réduire la portée des INSERTS contenus dans chaque commit sans réel effet; l'accès ultérieur au fichier db déclenche la même exception.Difficulté à exécuter des INSERTS simultanés sur une base de données SQLite en C#

Des pensées? Je suis perplexe et je ne suis pas sûr où regarder la prochaine ...

Répondre

5

Mettez à jour votre code d'insertion de sorte que s'il rencontre une exception indiquant le verrouillage de la base de données, il attend un peu et essaie à nouveau. Augmentez le temps d'attente par incréments aléatoires à chaque fois (l'algorithme "random backoff"). Cela devrait permettre aux threads de saisir le verrou d'écriture global. Les performances seront médiocres, mais le code devrait fonctionner sans modification significative.

Cependant, SQLite n'est pas approprié pour une modification hautement simultanée. Vous avez deux solutions permanentes:

  • Déplacer vers une base de données « réel », tels que PostgreSQL ou MySQL
  • Sérialise toutes vos modifications de base de données à travers un fil, pour éviter les modifications de SQLite.
+0

cool .. j'ai considéré ceci, mais est-ce que cela garantit réellement qu'il ne se verrouillera jamais? J'ai l'impression que cela prendra plus de temps (en d'autres termes, réduire les chances de) de se refermer. Im opérant sur une très grande quantité de données et le processus prendra des heures sinon des jours ... –

+0

aussi quand vous dites hautement concurrente, que voulez-vous dire exactement? mon application fonctionnera entre 1 et 20 de ces discussions dans des conditions normales d'utilisation. est-ce considéré comme une concurrence élevée? –

+1

Si sérialisé à un thread, il n'aura pas d'erreurs de verrouillage. Alternativement, si vous réessayez sur les erreurs de verrouillage, ils n'empêcheront pas le programme de se terminer. SQLite n'est pas conçu pour la concurrence, mais il peut être fait pour fonctionner pour quelques threads qui ne sont pas souvent INSERT. Si vous avez plus de 3 threads qui insèrent tous, vous devez utiliser une base de données différente. –

1

Deux choses à vérifier:

1) a confirmé que votre version de SQLite a été compilé avec le support FILET

2) Confirmez que vous n'êtes pas l'ouverture de la base de données EXCLUSIF

0

Je n'étais pas en C#, mais plutôt sous Android, mais j'ai contourné cette erreur "database is locked" en maintenant la base de données sqlite toujours ouverte dans la classe wrapper qui la possède, pendant toute la durée de vie de la classe wrapper. Chaque insertion faite dans cette classe peut alors être dans son propre thread (parce que, selon votre situation de stockage de données, carte SD par rapport à la mémoire de l'appareil etc., l'écriture db pourrait prendre longtemps), et j'ai même essayé de l'étrangler. douzaine insèrent des threads à la fois, et chacun a été très bien géré car la méthode insert n'avait pas à s'inquiéter de l'ouverture/fermeture d'une DB. Je ne suis pas sûr si les cycles de vie persistants de la base de données sont considérés comme du bon style, mais cela peut être considéré comme mauvais dans la plupart des cas, mais pour l'instant cela fonctionne plutôt bien.