sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Comment déverrouiller la base de données pour que cela fonctionne?
sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Comment déverrouiller la base de données pour que cela fonctionne?
Réponses:
Dans Windows, vous pouvez essayer ce programme http://www.nirsoft.net/utils/opened_files_view.html pour découvrir que le processus gère le fichier db. Essayez de fermer ce programme pour déverrouiller la base de données
Sous Linux et macOS, vous pouvez faire quelque chose de similaire, par exemple, si votre fichier verrouillé est development.db:
$ fuser development.db
Cette commande montrera quel processus verrouille le fichier:
> development.db: 5430
Tuez simplement le processus ...
tuer -9 5430
... Et votre base de données sera déverrouillée.
kill
devrait aller, mais vous devez faire attention à le tuer correctement, et il kill -9
est probablement faux et / ou excessif. Si le processus est suspendu et ne mourra pas autrement, vous en avez parfois besoin kill -9
. Mais vous ne voulez pas aller tuer le travail de production principal juste pour pouvoir signaler que la base de données n'est plus verrouillée!
J'ai provoqué le verrouillage de ma base de données sqlite en plantant une application lors d'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
sqlite> .dump PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; /**** ERROR: (5) database is locked *****/ ROLLBACK; -- due to errors
FOREIGN KEY constraint failed (RELEASE RESTOREPOINT)
La page DatabaseIsLocked répertoriée ci-dessous n'est plus disponible. La page Verrouillage de fichiers et accès simultané décrit les modifications liées au verrouillage de fichiers introduites dans la v3 et peut être utile aux futurs lecteurs. https://www.sqlite.org/lockingv3.html
La page SQLite wiki DatabaseIsLocked offre une bonne explication de ce message d'erreur. Il indique, en partie, que la source de conflit est interne (au processus émettant l'erreur).
Ce que cette page n'explique pas, c'est comment SQLite décide que quelque chose dans votre processus détient un verrou et quelles conditions pourraient conduire à un faux positif.
La suppression du fichier -journal semble être une idée terrible. Il est là pour permettre à sqlite de restaurer la base de données dans 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, vous vous retrouvez avec une base de données corrompue. Citant une page du site sqlite :
Si une panne ou une coupure de courant se produit et qu'un journal actif est laissé sur le disque, il est essentiel que le fichier de base de données d'origine et le journal actif restent sur le disque avec leurs noms d'origine jusqu'à ce que le fichier de base de données soit ouvert par un autre processus SQLite et restauré. . [...]
Nous pensons qu'un mode de défaillance commun pour la récupération SQLite se produit comme ceci: Une panne de courant se produit. Une fois le courant rétabli, un utilisateur ou un administrateur système bien intentionné commence à rechercher des dommages sur le disque. Ils voient leur fichier de base de données nommé "important.data". Ce dossier leur est peut-être familier. Mais après l'accident, il y a aussi un journal chaud nommé "important.data-journal". L'utilisateur supprime ensuite le journal actif, pensant qu'il aide à nettoyer le système. Nous ne connaissons aucun moyen d'empêcher cela autre que la formation des utilisateurs.
La restauration est censée se produire automatiquement à la prochaine ouverture de la base de données, mais elle échouera si le processus ne peut pas verrouiller la base de données. Comme d'autres l'ont dit, l'une des raisons possibles est qu'un autre processus est actuellement ouvert. Une autre possibilité est un verrou NFS périmé, si la base de données se trouve sur un volume NFS. Dans ce cas, une solution consiste à remplacer le fichier de base de données par une nouvelle copie qui n'est pas verrouillée sur le serveur NFS (mv database.db original.db; cp original.db database.db). Notez que la FAQ sqlite recommande la prudence concernant l'accès simultané aux bases de données sur les volumes NFS, en raison des implémentations bogues du verrouillage des fichiers NFS.
Je ne peux pas expliquer pourquoi la suppression d'un fichier -journal vous permettrait de verrouiller une base de données que vous ne pouviez pas auparavant. Est-ce reproductible?
Soit dit en passant, la présence d'un fichier -journal ne signifie pas nécessairement qu'il y a eu un plantage ou qu'il y a des modifications à annuler. Sqlite a plusieurs modes de journal différents et dans les modes PERSIST ou TRUNCATE, il laisse toujours le fichier -journal en place et modifie le contenu pour indiquer s'il y a ou non des transactions partielles à annuler.
Si vous souhaitez supprimer une erreur «la base de données est verrouillée», procédez comme suit:
Si un processus a un verrou sur une base de données SQLite et se bloque, la base de données reste verrouillée en permanence. C'est le problème. Ce n'est pas qu'un autre processus a un verrou.
les fichiers db SQLite ne sont que des fichiers, donc la première étape serait de s'assurer qu'il n'est pas en lecture seule. L'autre chose à faire est de vous assurer que vous n'avez pas une sorte de visualiseur DB SQLite GUI avec la base de données ouverte. Vous pouvez avoir la base de données ouverte dans un autre shell, ou votre code peut avoir la base de données ouverte. En règle générale, vous voyez cela si un thread différent ou une application telle que SQLite Database Browser a la base de données ouverte pour l'écriture.
J'ai eu ce problème tout à l'heure, en utilisant une base de données SQLite sur un serveur distant, stockée sur une monture NFS. SQLite n'a pas pu obtenir de verrou après que la session shell distante que j'ai utilisée s'est arrêté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'abord déplacer puis de recopier la base de données). Mais après l'avoir copiée sur un système non NFS, la base de données est devenue utilisable et aucune donnée ne semble avoir été perdue.
Mon verrou a été provoqué par le plantage du système et non par un processus de blocage. Pour résoudre ce problème, j'ai simplement renommé le fichier, puis je l'ai recopié vers son nom et son emplacement d'origine.
Utiliser un shell Linux qui serait ...
mv mydata.db temp.db
cp temp.db mydata.db
J'ai ajouté " Pooling=true
" à la chaîne de connexion et cela a fonctionné.
J'ai trouvé la documentation des différents états de verrouillage dans SQLite très utile. Michael, si vous pouvez effectuer des lectures mais ne pouvez pas effectuer d'écritures dans la base de données, cela signifie qu'un processus a obtenu un verrou RÉSERVÉ sur votre base de données mais n'a pas encore exécuté l'écriture. Si vous utilisez SQLite3, il y a un nouveau verrou appelé PENDING où plus aucun processus n'est autorisé à se connecter mais les connexions existantes peuvent toujours effectuer des lectures, donc si c'est le problème, vous devriez le regarder à la place.
J'ai un tel problème dans l'application, qui accède à SQLite à partir de 2 connexions - l'une était en lecture seule et la seconde pour l'écriture et la lecture. Il semble que cette connexion en lecture seule ait bloqué l'écriture à partir de la deuxième connexion. Enfin, il s'avère qu'il est nécessaire de finaliser ou, au moins, de réinitialiser les déclarations préparées IMMÉDIATEMENT après utilisation. Jusqu'à l'ouverture de l'instruction préparée, la base de données a été bloquée pour l'écriture.
N'OUBLIEZ PAS D'APPEL:
sqlite_reset(xxx);
ou
sqlite_finalize(xxx);
Certaines fonctions, comme INDEX'ing, peuvent prendre très longtemps - et elles verrouillent toute la base de données pendant son exécution. Dans des cas comme celui-ci, il est possible qu'il n'utilise même pas le fichier journal!
Donc, le meilleur / seul moyen de vérifier si votre base de données est verrouillée car un processus y écrit activement (et donc vous devriez le laisser tranquille jusqu'à ce qu'il soit terminé) est de md5 (ou md5sum sur certains systèmes) le fichier deux fois . Si vous obtenez une somme de contrôle différente, la base de données est en cours d'écriture et vous ne voulez vraiment VRAIMENT pas tuer -9 ce processus car vous pouvez facilement vous retrouver avec une table / base de données corrompue si vous le faites.
Je le répète, car 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 verrou en écriture pour une bonne raison, et de partir de là. Parfois, la bonne solution n'est qu'une pause-café.
La seule façon de créer cette situation verrouillée mais non en cours d'écriture est si votre programme s'exécute BEGIN EXCLUSIVE
, car il voulait faire des modifications de table ou quelque chose, alors pour une raison quelconque, n'envoie jamais de END
suite et le processus ne se termine jamais . Les trois conditions remplies sont très improbables dans tout code correctement écrit, et en tant que tel 99 fois sur 100 lorsque quelqu'un veut tuer -9 son processus de verrouillage, le processus de verrouillage verrouille réellement votre base de données pour une bonne raison. Les programmeurs n'ajoutent généralement pas la BEGIN EXCLUSIVE
condition à moins qu'ils n'en aient vraiment besoin, car cela 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 À L'INTÉRIEUR du fichier, comme l'ont indiqué plusieurs réponses - il réside dans le noyau du système d'exploitation. Le processus exécuté BEGIN EXCLUSIVE
a demandé au système d'exploitation qu'un verrou soit placé sur le fichier. Même si votre processus exclusif est tombé en panne, votre système d'exploitation sera en mesure de 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 ne la verrouille activement !! 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 de fusion (c'est une bonne démonstration de pourquoi: /unix/94316/fuser-vs-lsof- vérifier les fichiers en cours d'utilisation ). Alternativement, si vous avez DTrace (OSX), vous pouvez utiliser iosnoop sur le fichier.
Quelque chose de similaire m'est arrivé - mon application Web a pu lire à partir de la base de données, mais n'a pu effectuer aucune insertion ou mise à 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.
Ce lien résout le problème. : Lorsque Sqlite donne: Erreur de base de données verrouillée Il a résolu mon problème peut vous être utile.
Et vous pouvez utiliser le début de la transaction et la fin de la transaction pour ne plus verrouiller la base de données à l'avenir.
Cela devrait être le problème interne d'une base de données ... Pour moi, cela s'est manifesté après avoir essayé de parcourir la base de données avec "SQLite manager" ...
Donc, si vous ne trouvez pas un autre processus, connectez-vous à la base de données et que vous ne pouvez pas le corriger, essayez simplement cette solution radicale:
rake db:migrate
"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, cela donnerait cette erreur lors de sa prochaine exécution. La solution était de fermer la fenêtre du terminal puis de l'ouvrir à nouveau. Ça n'a pas de sens pour moi, mais ça a marché.
J'ai eu le même problème. Apparemment, la fonction de restauration semble remplacer le fichier db par le journal qui est le même que le fichier db mais sans la modification la plus récente. J'ai implémenté cela dans mon code ci-dessous et cela fonctionne bien depuis lors, alors qu'avant mon code resterait bloqué dans la boucle car la base de données restait verrouillée.
J'espère que cela t'aides
##############
#### 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 )
Une raison courante pour obtenir cette exception est lorsque vous essayez d'effectuer une opération d'écriture tout en conservant des ressources pour une opération de lecture. Par exemple, si vous sélectionnez dans une table, puis essayez de METTRE À JOUR quelque chose que vous avez sélectionné sans fermer d'abord votre ResultSet.
Je rencontrais également des erreurs "la base de données est verrouillée" dans une application multi-thread, qui semble être le code de résultat SQLITE_BUSY , et je l'ai résolu en définissant sqlite3_busy_timeout sur quelque chose de convenablement long comme 30000.
(En passant, comme c'est étrange que sur une question de 7 ans personne ne l'ait déjà découvert! SQLite est vraiment un projet particulier et étonnant ...)
Avant de descendre l'option de redémarrage, il vaut la peine de voir si vous pouvez trouver l'utilisateur de la base de données sqlite.
Sous Linux, on peut employer fuser
à cet effet:
$ fuser database.db
$ fuser database.db-journal
Dans mon cas, j'ai obtenu la réponse suivante:
philip 3556 4700 0 10:24 pts/3 00:00:01 /usr/bin/python manage.py shell
Ce qui a montré que j'avais un autre programme Python avec le pid 3556 (manage.py) en utilisant la base de données.
Une vieille question, avec beaucoup de réponses, voici les étapes que j'ai récemment suivies en lisant les réponses ci-dessus, mais dans mon cas, le problème était dû au partage des ressources cifs. Ce cas n'a pas été signalé précédemment, alors espérons qu'il aide quelqu'un.
Essayez 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 db SQLite sur un dossier partagé NFS, vérifiez ce point de la FAQ SQLite et passez en revue vos options de configuration de montage pour vous assurer d'éviter les verrous, 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
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 pu exécuter des requêtes sur la base de données avec succès, sur le troisième, je pensais recevoir le message "la base de données est verrouillée".
Le truc avec cette 3ème machine, c'est qu'il ne restait plus d'espace /var
. Chaque fois que j'ai essayé d'exécuter une requête dans N'IMPORTE QUELLE base de données SQLite située dans ce système de fichiers, j'ai reçu le message "la base de données est verrouillée" et également cette erreur sur les journaux:
8 août 10:33:38 noyau server01: lockd: impossible de surveiller 172.22.84.87
Et celui-ci aussi:
8 août 10:33:38 server01 rpc.statd [7430]: échec de l'insertion: écriture /var/lib/nfs/statd/sm/other.server.name.com: aucun espace disponible sur le périphérique 8 août 10:33: 38 server01 rpc.statd [7430]: STAT_FAIL à server01 pour SM_MON de 172.22.84.87
Après la gestion de la situation spatiale, tout est revenu à la normale.
Si vous essayez de déverrouiller la base de données Chrome pour la visualiser avec SQLite , simplement Chrome.
les fenêtres
%userprofile%\Local Settings\Application Data\Google\Chrome\User Data\Default\Web Data
or
%userprofile%\Local Settings\Application Data\Google\Chrome\User Data\Default\Chrome Web Data
Mac
~/Library/Application Support/Google/Chrome/Default/Web Data
D'après vos commentaires précédents, vous avez dit qu'un dossier de journal était présent.
Cela peut signifier que vous avez ouvert une transaction (EXCLUSIVE?) Et que vous n'avez pas encore validé les données. Votre programme ou un autre processus a-t-il laissé le journal derrière vous ??
Le redémarrage du processus sqlite examinera le fichier journal et nettoiera toutes les actions non validées et supprimera le fichier -journal.
Comme l'a dit Seun Osewa, parfois un processus zombie se trouve dans le terminal avec une serrure acquise, même si vous ne le pensez pas possible. Votre script s'exécute, se bloque et vous revenez à l'invite, mais il y a un processus zombie engendré quelque part par un appel à la bibliothèque, et ce processus a le verrou.
La fermeture du terminal dans lequel vous étiez (sous OSX) peut fonctionner. Le redémarrage fonctionnera. Vous pouvez rechercher des processus "python" (par exemple) qui ne font rien et les tuer.
vous pouvez essayer ceci: .timeout 100
pour définir le délai d'expiration. Je ne sais pas ce qui se passe en ligne de commande mais en C # .Net quand je fais cela: "UPDATE table-name SET column-name = value;"
je reçois la base de données est verrouillée mais cela"UPDATE table-name SET column-name = value"
ça va bien.
Il ressemble à ce que vous ajoutez; sqlite recherchera une commande supplémentaire.