Comment débloquer une base de données SQLite?

sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked

Comment débloquer la base de données pour que cela fonctionne?

218
demandé sur Noah 2008-09-30 02:35:49

30 réponses

sous windows vous pouvez essayer ce programme http://www.nirsoft.net/utils/opened_files_view.html pour découvrir que le processus est de traiter le fichier db. Essayez fermé ce programme pour la base de données de déverrouillage

dans Linux et macOS vous pouvez faire quelque chose de similaire, par exemple, si votre fichier verrouillé est le développement.db:

$ fuser de développement.db

cette commande indique le processus de verrouillage le dossier:

> développement.db: 5430

tue le processus...

kill -9 5430

...Et votre base de données sera débloqué.

225
répondu noneno 2016-06-17 14:41:35

j'ai fait verrouiller mon SQLite db en écrasant une application pendant une écriture. Voici comment je l'ai corrigé:

echo ".dump" | sqlite old.db | sqlite new.db

tiré de: http://random.kakaopor.hu/how-to-repair-an-sqlite-database

82
répondu robert 2011-10-12 13:12:52

la page SQLite wiki DatabaseIsLocked offre une bonne explication de ce message d'erreur. Il y est dit, en partie, que la source de la contestation est interne (au processus à l'origine de l'erreur).

ce que cette page n'explique pas est comment SQLite décide que quelque chose dans votre processus détient un verrou et quelles conditions pourraient conduire à un faux positif.

51
répondu converter42 2008-10-20 14:24:02

Supprimer le fichier journal sonne comme une idée terrible. Il est là pour permettre à sqlite de ramener la base de données à un état cohérent après un crash. Si vous le supprimez alors que la base de données est dans un état incohérent, alors il vous reste une base de données corrompue. Citant une page du site sqlite :

si un crash ou une perte de puissance se produit et un journal chaud est laissé sur le disque, il est essentiel que la base de données originale dossier et le journal chaud restent sur le disque avec leurs noms originaux jusqu'à ce que le fichier de base de données est ouvert par un autre processus de SQLite et a roulé en arrière. [...]

nous soupçonnons qu'un mode de défaillance commun pour la récupération de SQLite se produit comme ceci: une panne de courant se produit. Une fois l'alimentation rétablie, un utilisateur bien intentionné ou un administrateur système commence à chercher des dommages sur le disque. Ils voient leur fichier de base de données nommé "important.données." Ce fichier est peut-être familier. Mais après le crash, il ya aussi un journal chaud nommé "important.données-journal". L'utilisateur supprime alors le journal chaud, pensant qu'ils aident à nettoyer le système. Nous ne connaissons aucun autre moyen d'empêcher cela que l'éducation des utilisateurs.

le retour en arrière est supposé se produire automatiquement la prochaine fois que la base de données est ouverte, mais il échouera si le processus ne peut pas verrouiller la base de données. Comme d'autres l'ont dit, une des raisons possibles en est qu'un autre processus a il ouvre. Une autre possibilité est un verrouillage NFS périmé, si la base de données est sur un volume NFS. Dans ce cas, une solution consiste à remplacer le fichier de la base de données par une nouvelle copie qui n'est pas verrouillée sur le serveur NFS (base de données mv.db d'origine.db; cp d'origine.db, base de données.DB.) Notez que la FAQ de sqlite recommande la prudence en ce qui concerne l'accès simultané aux bases de données sur les volumes NFS, en raison des implémentations buggées de verrouillage de fichiers NFS.

Je ne peux pas expliquer pourquoi supprimer un fichier journal laisserait vous verrouillez une base de données que vous ne pouviez pas avant. C'est que-il reproductible?

soit dit en passant, la présence d'un fichier journal ne signifie pas nécessairement qu'il y a eu un accident ou qu'il y a des changements qui doivent être annulés. Sqlite a quelques modes de journal différents, et dans les modes PERSIST ou TRUNCATE il laisse toujours le fichier-journal en place, et change le contenu pour indiquer s'il y a ou non des transactions partielles à retourner.

27
répondu Aaron 2009-06-22 14:25:15

si un procédé a une serrure sur une base SQLite et s'écrase, la base de données reste verrouillée de façon permanente. C'est ça le problème. Ce n'est pas qu'un autre processus ait une serrure.

12
répondu 2009-01-29 22:58:06

si vous voulez supprimer l'erreur "database is locked", suivez les étapes suivantes:

  1. Copiez votre fichier de base de données à un autre endroit.
  2. remplacer la base de données par la base de données copiée. Cela déréférencera tous les processus qui accédaient à votre fichier de base de données.
12
répondu vinayak jadi 2013-05-29 17:39:52

les fichiers SQLite db ne sont que des fichiers, donc la première étape serait de s'assurer qu'ils ne sont pas en lecture seule. L'autre chose à faire est de s'assurer que vous n'avez pas une sorte de visionneuse GUI SQLite DB avec la DB ouverte. Vous pouvez avoir le DB ouvert dans un autre shell, ou votre code peut avoir le DB ouvert. Typiquement vous verriez cela si un fil différent, ou une application telle que le navigateur de base de données SQLite a la base de données ouverte pour l'écriture.

10
répondu Heat Miser 2008-09-29 22:39:14

j'ai eu ce problème tout à l'heure, en utilisant une base de données SQLite sur un serveur distant, stockée sur un montage NFS. SQLite n'a pas été en mesure d'obtenir une serrure après que la session shell distante que j'ai utilisée s'est écrasée alors que la base de données était ouverte.

les recettes de récupération suggérées ci-dessus n'ont pas fonctionné pour moi (y compris l'idée de déménager d'abord et ensuite de copier la base de données en arrière). Mais après l'avoir copié sur un système non-NFS, la base de données est devenue utilisable et non des données semble avoir été perdu.

9
répondu jogojapan 2011-06-16 03:19:32

j'ai trouvé la documentation des différents états de verrouillage dans SQLite pour être très utile. Michael, si vous pouvez effectuer des lectures mais ne pouvez pas effectuer des Écritures à la base de données, cela signifie qu'un processus a obtenu un verrouillage réservé sur votre base de données mais n'a pas encore exécuté l'écriture. Si vous utilisez SQLite3, il y a une nouvelle serrure appelée PENDING où plus aucun processus n'est autorisé à se connecter mais les connexions existantes peuvent effectuer des lectures, donc si c'est le problème que vous je devrais plutôt regarder ça.

4
répondu Kyle Cronin 2008-11-14 18:44:35

Cette erreur peut être levée si le fichier est dans un dossier distant, comme un dossier partagé. J'ai changé la base de données en un répertoire local et ça a fonctionné parfaitement.

4
répondu Zequez 2012-09-12 20:29:35

ma serrure a été causée par un crash du système et non par un processus de suspension. Pour résoudre cela, j'ai simplement renommé le fichier puis copié à son nom d'origine et l'emplacement.

utilisant un shell linux qui serait...

mv mydata.db temp.db
cp temp.db mydata.db
3
répondu Ben L 2009-08-04 11:02:36

j'ai un tel problème dans l'application, l'accès à SQLite à partir de 2 connexions - Une était en lecture seule et la deuxième pour l'écriture et la lecture. Il semble que cette connexion en lecture seule bloque l'écriture à partir de la deuxième connexion. Enfin, il s'avère qu'il est nécessaire de finaliser ou, à tout le moins, de réinitialiser les déclarations préparées immédiatement après leur utilisation. Jusqu'à ce que la déclaration préparée soit ouverte, il a causé à la base de données a été bloqué pour l'écriture.

N'OUBLIEZ PAS L'APPEL:

sqlite_reset(xxx);

ou

sqlite_finalize(xxx);
3
répondu Mike Keskinov 2012-02-17 18:39:06

certaines fonctions, comme INDEX'ing, peuvent prendre beaucoup de temps - et verrouiller toute la base de données pendant qu'elle tourne. Dans des cas comme celui-ci, il pourrait même ne pas utiliser le fichier journal!

donc la meilleure/seule façon de vérifier si votre base de données est verrouillée parce qu'un processus lui écrit activement (et donc vous devriez le laisser seul jusqu'à ce qu'il ait terminé son fonctionnement) est de md5 (ou md5sum sur certains systèmes) le fichier deux fois. Si vous obtenez un checksum différent, la base de données est être écrit, et vous vraiment vraiment vraiment vraiment ne veulent pas tuer -9 ce processus parce que vous pouvez facilement finir avec une table/base de données corrompue si vous le faites.

je répète, parce que c'est important - la solution N'est pas de trouver le programme de verrouillage et de le tuer - c'est de trouver si la base de données a un verrouillage d'écriture pour une bonne raison, et aller de là. Parfois, la bonne solution est juste une pause-café.

la seule façon de créer ce si votre programme exécute BEGIN EXCLUSIVE , parce qu'il voulait faire quelques modifications de table ou quelque chose, alors pour quelque raison que ce soit, il n'envoie jamais de END par la suite, et le processus ne se termine jamais . Les trois conditions étant remplies est très peu probable dans n'importe quel code correctement écrit, et en tant que tel 99 fois sur 100 quand quelqu'un veut tuer -9 leur processus de verrouillage, le processus de verrouillage est en fait verrouiller votre base de données pour un une bonne raison. Les programmeurs n'ajoutent généralement pas la condition BEGIN EXCLUSIVE à moins qu'ils n'en aient vraiment besoin, parce qu'elle empêche la concurrence et augmente les plaintes des utilisateurs. SQLite lui-même ne l'ajoute que lorsqu'il en a vraiment besoin (comme lors de l'indexation).

enfin, le statut "verrouillé" n'existe pas dans le fichier comme plusieurs réponses l'ont indiqué - il réside dans le noyau du système d'exploitation. Le processus qui s'est déroulé BEGIN EXCLUSIVE a demandé à L'OS qu'un verrou soit placé sur le fichier. Même si votre processus exclusif s'est écrasé, votre système d'exploitation pourra déterminer s'il doit maintenir le verrouillage du fichier ou non!! Il n'est pas possible de se retrouver avec une base de données qui est verrouillée, mais aucun processus est activement verrouillage!! Quand il s'agit de voir quel processus verrouille le fichier, il est généralement préférable d'utiliser lsof plutôt que fuser (ceci est une bonne démonstration de pourquoi: https://unix.stackexchange.com/questions/94316/fuser-vs-lsof-to-check-files-in-use ). Sinon, si vous avez DTrace (OSX) vous pouvez utiliser iosnoop sur le fichier.

3
répondu J.J 2017-04-13 12:36:27

j'ai ajouté " Pooling=true " à la chaîne de connexion et cela a fonctionné.

3
répondu user1900210 2017-10-31 04:53:09

il m'est arrivé quelque chose de semblable - mon application web était capable de lire à partir de la base de données, mais ne pouvait pas effectuer d'inserts ou de mises à jour. Un redémarrage d'Apache a résolu le problème, au moins temporairement.

ce serait bien, cependant, de pouvoir retrouver la cause profonde.

2
répondu Michael Cox 2008-11-14 18:37:13

lsof la commande sur mon environnement Linux m'a aidé à comprendre qu'un processus était en cours pour garder le fichier ouvert.

Tué le processus et le problème a été résolu.

2
répondu PinkSheep 2011-09-16 20:29:25

ce lien résout le problème. : Quand Sqlite donne : Base de données verrouillée erreur Il a résolu mon problème peut être utile pour vous.

et vous pouvez utiliser begin transaction et end transaction pour ne pas rendre la base de données verrouillée à l'avenir.

2
répondu shreeji 2017-05-23 10:31:26

devrait être le problème interne d'une base de données...

Pour moi il a été manifesté après avoir essayé de parcourir la base de données avec "SQLite manager"...

Donc, si vous ne pouvez pas trouver un autre processus, connectez - vous à la base de données et vous ne pouvez pas le réparer., essayez juste cette solution radicale:

  1. fournir pour exporter vos tables (Vous pouvez utiliser "SQLite manager" sur Firefox)
  2. si la migration modifie votre schéma de base de données supprimer la dernière migration ratée
  3. renommez votre base de données.sqlite" fichier
  4. Exécuter "rake db:migrate" pour faire une nouvelle base de données de travail
  5. Fournir à donner les autorisations de base de données pour la table d'importation
  6. importer vos tables sauvegardées
  7. écrire la nouvelle migration
  8. L'exécuter avec " rake db:migrate "
2
répondu Davide Ganz 2017-10-31 04:52:35

j'ai rencontré ce même problème sur Mac OS X 10.5.7 en exécutant des scripts Python à partir d'une session de terminal. Même si j'avais arrêté les scripts et que la fenêtre du terminal se trouvait à l'invite de commande, elle donnait cette erreur la prochaine fois qu'elle courait. La solution était de fermer la fenêtre du terminal et de l'ouvrir à nouveau. Ça n'a pas de sens pour moi, mais ça a marché.

1
répondu Shawn Swaner 2009-06-12 20:20:21

j'ai eu la même erreur. Après 5 minets google-ing j'ai trouvé que je n'ai pas fermé un sorcier shell utilisaient le db. Il suffit de fermer et essayer de nouveau ;)

1
répondu Flow 2011-12-15 09:11:05

j'ai eu le même problème. Apparemment, la fonction rollback semble écraser le fichier db avec le journal qui est le même que le fichier db mais sans le changement le plus récent. J'ai implémenté ceci dans mon code ci-dessous et cela fonctionne bien depuis lors, alors qu'avant mon code serait juste coincé dans la boucle que la base de données est restée verrouillée.

Espérons que cette aide

mon code python

##############
#### Defs ####
##############
def conn_exec( connection , cursor , cmd_str ):
    done        = False
    try_count   = 0.0
    while not done:
        try:
            cursor.execute( cmd_str )
            done = True
        except sqlite.IntegrityError:
            # Ignore this error because it means the item already exists in the database
            done = True
        except Exception, error:
            if try_count%60.0 == 0.0:       # print error every minute
                print "\t" , "Error executing command" , cmd_str
                print "Message:" , error

            if try_count%120.0 == 0.0:      # if waited for 2 miutes, roll back
                print "Forcing Unlock"
                connection.rollback()

            time.sleep(0.05)    
            try_count += 0.05


def conn_comit( connection ):
    done        = False
    try_count   = 0.0
    while not done:
        try:
            connection.commit()
            done = True
        except sqlite.IntegrityError:
            # Ignore this error because it means the item already exists in the database
            done = True
        except Exception, error:
            if try_count%60.0 == 0.0:       # print error every minute
                print "\t" , "Error executing command" , cmd_str
                print "Message:" , error

            if try_count%120.0 == 0.0:      # if waited for 2 miutes, roll back
                print "Forcing Unlock"
                connection.rollback()

            time.sleep(0.05)    
            try_count += 0.05       




##################
#### Run Code ####
##################
connection = sqlite.connect( db_path )
cursor = connection.cursor()
# Create tables if database does not exist
conn_exec( connection , cursor , '''CREATE TABLE IF NOT EXISTS fix (path TEXT PRIMARY KEY);''')
conn_exec( connection , cursor , '''CREATE TABLE IF NOT EXISTS tx (path TEXT PRIMARY KEY);''')
conn_exec( connection , cursor , '''CREATE TABLE IF NOT EXISTS completed (fix DATE, tx DATE);''')
conn_comit( connection )
1
répondu Jared 2012-02-17 11:56:43

une raison commune pour obtenir cette exception est quand vous essayez de faire une opération d'écriture tout en maintenant des ressources pour une opération de lecture. Par exemple, si vous sélectionnez à partir d'une table, puis essayer de mettre à jour quelque chose que vous avez sélectionné sans fermer votre ensemble de résultats d'abord.

1
répondu Martin Carney 2012-10-24 17:33:42

avant de passer à l'option de redémarrage, il est intéressant de voir si vous pouvez trouver l'utilisateur de la base de données sqlite.

sous Linux, on peut employer fuser à cette fin:

$ fuser database.db

$ fuser database.db-journal

dans mon cas, j'ai eu la réponse suivante:

philip    3556  4700  0 10:24 pts/3    00:00:01 /usr/bin/python manage.py shell

qui a montré que j'avais un autre programme Python avec pid 3556 (manage.py) en utilisant la base de données.

1
répondu Philip Clarke 2017-07-20 18:38:27

une vieille question, avec beaucoup de réponses, voici les étapes que j'ai suivies récemment en lisant les réponses ci-dessus, mais dans mon cas le problème était dû au partage des ressources du cifs. Ce cas n'est pas signalé auparavant, alors espérons qu'il aide quelqu'un.

  • Vérifiez qu'aucune connexion n'est laissée ouverte dans votre code java.
  • Vérifiez qu'aucun autre processus n'utilise votre fichier SQLite db avec lsof.
  • vérifiez le propriétaire utilisateur de votre exécution le processus jvm a des permissions R / w sur le fichier.
  • essayer de forcer le mode de verrouillage sur l'ouverture de connexion avec

    final SQLiteConfig config = new SQLiteConfig();
    
    config.setReadOnly(false);
    
    config.setLockingMode(LockingMode.NORMAL);
    
    connection = DriverManager.getConnection(url, config.toProperties());
    

si vous utilisez votre fichier SQLite db dans un dossier partagé NFS, cochez ce point de la faq SQLite, et passez en revue vos options de configuration de montage pour vous assurer que vous évitez les serrures, comme décrit ici :

//myserver /mymount cifs username=*****,password=*****,iocharset=utf8,sec=ntlm,file,nolock,file_mode=0700,dir_mode=0700,uid=0500,gid=0500 0 0
1
répondu kothvandir 2017-10-31 04:54:15

j'ai eu cette erreur dans un scénario un peu différent de ceux décrits ici.

la base de données SQLite reposait sur un système de fichiers NFS partagé par 3 serveurs. Sur 2 des serveurs, j'ai réussi à lancer des requêtes sur la base de données avec succès, sur le troisième j'ai pensé recevoir le message "la base de données est verrouillée".

la chose avec cette 3ème machine était qu'il ne restait plus de place sur /var . Chaque fois que j'ai essayé d'exécuter une requête dans un SQLite base de données située dans ce système de fichiers j'ai reçu le message" la base de données est verrouillée "et aussi cette erreur sur les journaux:

8 Août à 10:33:38 server01 noyau: lockd: ne peut pas surveiller 172.22.84.87

et celui-ci aussi:

8 Août à 10:33:38 server01 rpc.statd[7430]: N'a pas inscrit: writing /var/lib/nfs/statd/sm/other.serveur.nom.com: plus de place sur l'appareil 8 août à 10:33:38 server01 RPC.statd [7430]: STAT_FAIL to server01 for SM_MON of 172.22.84.87

une fois la situation spatiale réglée, tout est redevenu normal.

1
répondu ederribeiro 2017-10-31 04:57:04

D'après vos commentaires précédents, vous avez dit que le fichier a-journal était présent.

cela pourrait signifier que vous avez ouvert et (exclusif?) et n'ont pas encore engagé les données. Votre programme ou un autre processus quitter le journal derrière??

redémarrer le processus sqlite va regarder le fichier journal et nettoyer toutes les actions non engagées et supprimer le fichier-journal.

0
répondu 2008-12-29 01:44:57

comme Seun Osewa l'a dit, parfois un processus zombie va s'asseoir dans le terminal avec une serrure acquise, même si vous ne pensez pas que ce soit possible. Votre script s'exécute, s'écrase, et vous retournez à l'invite, mais il y a un processus zombie engendré quelque part par un appel de bibliothèque, et ce processus a la serrure.

fermer le terminal dans lequel vous étiez (sur OSX) pourrait fonctionner. Le redémarrage sera le travail. Vous pouvez rechercher des processus "python" (par exemple) qui ne font rien, et tuer ils.

0
répondu wisty 2010-01-07 05:51:56

vous pouvez essayer ceci: .timeout 100 pour mettre le temps d'arrêt . Je ne sais pas ce qui se passe en ligne de commande mais dans C# .Net quand je fais ceci: "UPDATE table-name SET column-name = value;" j'obtiens la base de données est verrouillée mais ce "UPDATE table-name SET column-name = value" il va très bien.

il ressemble à quand vous ajoutez ;, sqlite va chercher plus de commande.

0
répondu nXqd 2010-06-27 11:28:28

j'ai eu cette erreur en utilisant Delphi avec les composants LiteDAC. Il s'est avéré que cela s'est produit seulement pendant l'exécution de mon application à partir de L'IDE Delphi si la propriété connectée a été définie True pour le composant de connexion SQLite (dans ce cas TLiteConnection).

0
répondu TheSteven 2014-03-14 20:32:55

administrateur est une petite (mais puissante) alternative de phpmyadmin que j'utilise pour surveiller la base de données sqlite. Pour une raison inconnue, la base de données a été verrouillée. Voici comment je l'ai corrigé.

  1. j'ai téléchargé le fichier sqlite sur mon système (FTP)
  2. supprimé le fichier sqlite en ligne
  3. Téléchargé le fichier vers le fournisseur d'hébergement

Il fonctionne très bien maintenant.

0
répondu Mohsin 2014-05-24 14:12:47