Frage

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

Wie schalte ich die Datenbank so wird diese Arbeit?

War es hilfreich?

Lösung

In Windows können Sie dieses Programm http://www.nirsoft.net/utils/opened_files_view .html , um herauszufinden, der Prozess db-Datei verarbeitet. Versuchen Sie das Programm für Unlock-Datenbank geschlossen

Unter Linux und Mac OS Sie etwas ähnliches, zum Beispiel tun, wenn Ihre gesperrte Datei ist development.db:

  

$ Fixierer development.db

Mit diesem Befehl wird zeigen, welcher Prozess die Datei blockiert:

  

> development.db: 5430

Sie einfach den Prozess töten ...

  

kill -9 5430

... Und Ihre Datenbank freigeschaltet werden.

Andere Tipps

Ich verursachte meine sqlite db durch Absturz einer App während eines Schreib gesperrt werden. Hier ist, wie ich es fest:

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

Entnommen: http://random.kakaopor.hu/how-to-repair- ein-sQLite-Datenbank

Die DatabaseIsLocked Seite unten aufgeführt ist nicht mehr verfügbar. Die File Locking und Concurrency Seite beschreibt Änderungen im Zusammenhang mit in v3 eingeführt Sperren von Dateien und kann für zukünftige Leser nützlich sein. https://www.sqlite.org/lockingv3.html

Das SQLite-Wiki DatabaseIsLocked Seite bietet eine gute Erklärung für diese Fehlermeldung . Darin heißt es, zum Teil, dass die Quelle des Anstoßes intern ist (auf den Prozess der Fehler emittierend).

Was diese Seite nicht erklärt ist, wie SQLite entscheidet, dass etwas in Ihrem Prozess eine Sperre hält und welche Bedingungen zu einem falsch positiven führen könnte.

die -Journal Datei löschen, klingt wie eine schreckliche Idee. Es ist da SQLite zu ermöglichen nach einem Absturz der Datenbank in einen konsistenten Zustand zurückversetzen. Wenn Sie es löschen, während die Datenbank in einem inkonsistenten Zustand ist, dann sind Sie mit einer beschädigten Datenbank verlassen. Unter Berufung auf eine Seite aus der SQLite Website :

  

Wenn ein Absturz oder Stromausfall auftritt und eine heiße Zeitschrift ist auf der Platte gelassen, ist es wichtig, dass die ursprüngliche Datenbankdatei und die heiße Zeitschrift bleiben auf der Festplatte mit ihren ursprünglichen Namen, bis die Datenbankdatei von einem anderen SQLite Prozess geöffnet und zurückgerollt. [...]

     

Wir vermuten, dass eine gemeinsame Fehlermodus für SQLite Erholung wie dies geschieht: Ein Stromausfall auftritt. Nach dem Einschalten wieder hergestellt wird, beginnt ein gut gemeinte Benutzer oder Systemadministrator um für Schäden auf die Festplatte suchen. Sie sehen ihre Datenbankdatei „important.data“ genannt. Diese Datei ist vielleicht vertraut ihnen. Aber nach dem Absturz, gibt es auch eine heiße Zeitschrift namens „important.data-journal“. Der Benutzer löscht dann die heiße Zeitschrift, zu denken, dass sie das System zur Reinigung helfen. Wir kennen keine Möglichkeit, diese andere als Benutzer Bildung zu verhindern.

Der Rollback sollte die Datenbank automatisch das nächste Mal passieren wird geöffnet, aber es wird fehlschlagen, wenn der Prozess die Datenbank nicht sperren können. Wie andere gesagt haben, ist ein möglicher Grund dafür, dass zur Zeit von einem anderen Prozess geöffnet hat. Eine weitere Möglichkeit ist eine veraltete NFS-Sperre, wenn die Datenbank auf einem NFS-Volume ist. In diesem Fall ist eine Behelfslösung der Datenbank-Datei mit einer neuen Kopie zu ersetzen, das nicht auf dem NFS-Server (mv database.db original.db; cp original.db database.db) gesperrt ist. Beachten Sie, dass die SQLite-FAQ Vorsicht in Bezug auf den gleichzeitigen Zugriff auf Datenbanken auf NFS-Volumes, weil der Buggy-Implementierungen von NFS-Dateisperren empfiehlt.

Ich kann nicht erklären, warum eine -Journal Datei zu löschen würde Sie eine Datenbank sperren, die Sie vorher nicht konnte. Ist das reproduzierbar?

Durch die Art und Weise, das Vorhandensein einer -Journal Datei bedeutet nicht unbedingt, dass es ein Unfall war oder dass es Änderungen rückgängig gemacht werden. SQLite hat ein paar verschiedene Journal-Modi und in den Modi PERSIST oder TRUNCATE es verlässt die -Journal Datei an Ort und Stelle immer, und ändert den Inhalt, um anzuzeigen, ob es sind teilweise Transaktionen rückgängig zu machen.

Wenn Sie folgen einer „Datenbank ist gesperrt“ Fehler zu entfernen, dann die folgenden Schritte:

  1. Kopieren Sie Ihre Datenbank-Datei an einen anderen Ort.
  2. Ersetzen Sie die Datenbank mit der Datenbank kopiert. Dies wird dereferenzieren alle Prozesse, die Ihre Datenbankdatei zugreifen würde.

Wenn ein Prozess eine Sperre auf einer SQLite-DB hat und stürzt ab, bleibt die DB dauerhaft gesperrt. Das ist das Problem. Es ist nicht, dass ein anderer Prozess eine Sperre hat.

Die SQLite-DB-Dateien sind nur Dateien, so dass der erste Schritt, um sicherzustellen, wäre es nicht schreibgeschützt ist. Das andere, was zu tun ist, um sicherzustellen, dass Sie nicht mit der DB offen irgendeine Art von GUI SQLite DB-Viewer haben. Sie könnten der DB in einer anderen Shell geöffnet haben, oder der Code kann die DB geöffnet haben. Normalerweise würden Sie das sehen, wenn ein anderer Thread oder Anwendung wie SQLite Database Browser die DB zum Schreiben geöffnet hat.

Ich hatte dieses Problem gerade jetzt, eine SQLite-Datenbank auf einem Remote-Server verwendet wird, auf einem NFS-Mount gespeichert. SQLite war nicht in der Lage, eine Sperre zu erhalten, nachdem der Remote-Shell-Sitzung habe ich abgestürzt war, während die Datenbank geöffnet war.

Die Rezepte für die Wiederherstellung vorgeschlagen oben nicht für mich arbeiten (einschließlich der Idee zum ersten Schritt und dann die Datenbank zurückkopieren). Aber nachdem sie ein nicht-NFS-System zu kopieren, wurde die Datenbank verwendbar und nicht die Daten scheinen verloren.

Meine Sperre wurde durch das System abstürzt verursacht und nicht durch einen hängenden Prozess. Um dies zu beheben ich einfach die Datei dann umbenannt es kopiert zurück zu seinem ursprünglichen Namen und Lage.

Mit einem Linux-Shell, das wäre ...

mv mydata.db temp.db
cp temp.db mydata.db

Ich habe "Pooling=true" zu Verbindungszeichenfolge und es hat funktioniert.

fand ich die Dokumentation der verschiedenen Zustände von in SQLite Sperren sehr hilfreich sein. Michael, wenn man liest ausführen kann, aber nicht ausführen Schreiben in die Datenbank, das bedeutet, dass ein Prozess ein reserviertes Sperre auf die Datenbank bekommen hat, aber nicht die Schreib noch ausgeführt. Wenn Sie SQLite3 verwenden, gibt es eine neue Sperre genannt PENDING, wo keine mehr Prozesse erlaubt sind zu verbinden, aber bestehende Verbindungen können Schweller durchführen liest, so dass, wenn dies das Problem ist, sollten Sie das betrachten, statt.

Dieser Fehler kann ausgelöst werden, wenn die Datei in einem Remote-Ordner ist, wie ein freigegebener Ordner. Ich habe die Datenbank in einem lokalen Verzeichnis und es funktionierte perfekt.

Ich habe ein solches Problem in der App, die von zwei Verbindungen SQLite zugreifen - ein schreibgeschützt wurde und die zweite für das Schreiben und Lesen. Es sieht aus wie die schreibgeschützte Verbindung von der zweiten Verbindung blockiert zu schreiben. Schließlich wird es stellt sich heraus, dass es erforderlich ist, zum Abschluss zu bringen oder zumindest zurückgesetzt vorbereitete Anweisungen sofort nach Gebrauch. Bis vorbereitete Anweisung geöffnet wird, es verursacht Datenbank zum Schreiben blockiert wurde.

NICHT ANRUF VERGESSEN:

sqlite_reset(xxx);

oder

sqlite_finalize(xxx);

Einige Funktionen, wie INDEX'ing, kann eine sehr lange Zeit in Anspruch nehmen - und es sperrt die gesamte Datenbank, während es ausgeführt wird. In Fällen, so könnte es nicht einmal die Journal-Datei verwenden!

So ist der beste / einzige Weg, um zu überprüfen, ob Ihre Datenbank gesperrt ist, weil ein Prozess aktiv ist schriftlich (und daher sollten Sie ihm die Hölle in Ruhe lassen, bis sie seinen Betrieb abgeschlossen) zu md5 (oder md5sum auf einigen Systemen) die Datei zweimal. Wenn Sie eine andere Prüfsumme erhalten, die Datenbank geschrieben wird, und Sie wirklich wirklich wirklich nicht wollen, zu töten -9 diesen Prozess, weil man leicht mit einer beschädigten Tabelle / Datenbank landen kann, wenn Sie tun.

Ich werde wiederholen, weil es wichtig ist - die Lösung ist nicht das Verriegelungsprogramm zu finden und töten - es zu finden ist, wenn die Datenbank eine Schreibsperre für einen guten Grund hat, und geht von dort aus. Manchmal ist die richtige Lösung ist nur eine Kaffeepause.

Der einzige Weg, dies zu schaffen Locked-but-not-being-geschrieben-to Situation, wenn Ihr Programm läuft BEGIN EXCLUSIVE, weil er wollte einige Tabellenänderungen oder etwas tun, dann aus irgendeinem Grund nie danach eine END sendet, < strong> und der Prozess endet nie . Alle drei Bedingungen erfüllt werden, ist in jedem richtig geschriebenen Code höchst unwahrscheinlich, und als solche in 99 von 100, wenn jemand will, um Ihre Datenbank für einen guten Grund töten -9 ihre Verriegelungsvorgang wird der Verriegelungsvorgang Verriegelung tatsächlich. Programmierer normalerweise nicht die BEGIN EXCLUSIVE Bedingung hinzufügen, wenn sie wirklich brauchen, weil sie die Parallelität verhindert und Beschwerden von Benutzern erhöht. SQLite selbst fügt es nur, wenn es braucht, um wirklich (wie bei der Indizierung).

Schließlich ist die ‚gesperrt‘ Status in der Datei nicht vorhanden ist, da mehrere Antworten angegeben haben - es liegt in den Kernel des Betriebssystems. Der Prozess, die BEGIN EXCLUSIVE lief von dem O angefordert eine Sperre für die Datei platziert werden. Selbst wenn Ihr exklusiver Prozess abgestürzt ist, wird Ihr O Lage sein, um herauszufinden, ob sie die Dateisperre halten sollen oder nicht !! Es ist nicht möglich, mit einer Datenbank, um am Ende der gesperrt ist, aber kein Prozess aktiv es blockiert !! Wenn es um das Sehen kommt, welcher Prozess die Datei blockiert, ist es in der Regel besser eher zu verwenden lsof als Fixiereinheit (das ist eine gute Demonstration, warum: https://unix.stackexchange.com/questions/94316/fuser-vs-lsof-to-check-files-in-use ) . Alternativ, wenn Sie DTrace (OSX) haben, können Sie auf die Datei verwenden iosnoop.

Ich hatte gerade etwas Ähnliches passiert mir - meine Web-Anwendung in der Lage war, aus der Datenbank zu lesen, konnte aber keine Einfügungen oder Aktualisierungen durchführen. Ein Neustart von Apache löste das Problem zumindest vorübergehend.

Es wäre schön, aber in der Lage sein, die Ursache ausfindig zu machen.

lsof Befehl auf meiner Linux-Umgebung hat mir geholfen, es herauszufinden, dass ein Prozess halten hing die Datei geöffnet.
Tötete den Prozess und Problem gelöst wurde.

Dieser Link, um das Problem lösen. : Wenn SQLite gibt: Datenbank gesperrt Fehler Es löste mein Problem für Sie nützlich sein können.

Und können Sie die Transaktion und Ende Transaktion zu machen, um nicht Datenbank gesperrt in Zukunft nutzen beginnen.

Sollte eine Datenbank internes Problem sein ...
Für mich ist es wurde nach dem Versuch durchsuchen Datenbank mit „SQLite Manager“ manifestiert ...
Also, wenn Sie nicht einen anderen Prozess eine Verbindung zur Datenbank finden und man kann einfach nicht fix it, nur versuchen, diese radikale Lösung:

  1. Geben Sie Ihre Tabellen exportieren (Sie können "SQLite Manager" auf Firefox verwenden)
  2. Wenn die Migration ändern Sie Ihr Datenbankschema die letzte fehlgeschlagenen Migration löscht
  3. Benennen Sie Ihre "database.sqlite" Datei
  4. Ausführen "rake db: wandern", um eine neue Arbeits Datenbank zu machen
  5. Geben Sie die richtigen Berechtigungen für Datenbank für Tabelle des importierenden geben
  6. Importieren Sie Ihre gesicherten Tabellen
  7. Schreiben Sie die neue Migration
  8. Führen Sie es mit "rake db:migrate"

Ich lief in das gleiche Problem auf Mac OS X 10.5.7 läuft Python-Skripte aus einer Terminal-Sitzung. Auch wenn ich die Skripte und die Terminal-Fenster saßen an der Eingabeaufforderung aufgehört hatte, würde es diesem Fehler das nächste Mal gibt sie liefen. Die Lösung war die Terminal-Fenster zu schließen und dann wieder öffnen. Macht keinen Sinn für mich, aber es hat funktioniert.

Ich hatte gerade den gleichen Fehler. Nach 5 minets google-ing fand ich, dass ich eine Schale Hexe geschlossen didun't die db verwendet haben. Schließen Sie es einfach und versuchen Sie es erneut;)

Ich hatte das gleiche Problem. Offenbar scheint die Rollback-Funktion, um die Datenbankdatei mit der Zeitschrift zu überschreiben, die die gleiche wie die db-Datei ist aber ohne die letzte Änderung. Ich habe dies unten in meinem Code implementiert und es ist seitdem fein gearbeitet, während sie vor meinem Code nur in der Schleife stecken bleiben würde, wie die Datenbank gesperrt blieb.

Hope, das hilft

mein Python-Code

##############
#### 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 )

Ein häufiger Grund für diese Ausnahme immer, wenn Sie immer noch versuchen, einen Schreibvorgang zu tun, während Ressourcen für einen Lesevorgang zu halten. Zum Beispiel, wenn Sie aus einer Tabelle auswählen und dann versuchen, etwas bearbeiten Sie ohne Schließen Sie Ihre ResultSet zuerst ausgewählt haben.

Bevor Sie die Option für den Neustart nach unten geht, lohnt es sich, zu sehen, wenn Sie den Benutzer der SQLite-Datenbank finden können.

Unter Linux kann man fuser zu diesem Zweck eingesetzt werden:

$ fuser database.db

$ fuser database.db-journal

In meinem Fall habe ich die folgende Antwort:

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

Was hat gezeigt, dass ich eine andere Python-Programm mit pid 3556 (manage.py) hatte mit der Datenbank.

Eine alte Frage, mit einer Menge Antworten, hier die Schritte, die ich vor kurzem die Antworten oben befolgt habe zu lesen, aber in meinem Fall war das Problem aufgrund CIFS gemeinsamen Nutzung von Ressourcen. Dieser Fall ist bisher nicht berichtet, so hoffen, dass es jemand hilft.

  • Überprüfen Sie keine Verbindungen in Ihrem Java-Code offen gelassen werden.
  • keine anderen Prozesse prüfen sind Ihre SQLite db-Datei mit lsof verwenden.
  • Überprüfen Sie den Benutzer Besitzer Ihres laufenden Jvm Prozess r / w Berechtigungen über die Datei hat.
  • Versuchen Sie den Lock-Modus auf der Verbindungsöffnung zu zwingen mit

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

Wenn Sie Ihre SQLite DB-Datei über einen freigegebenen NFS-Ordner verwenden, überprüfen Sie dieser Punkt der SQLite-FAQ, und Ihre Montage Konfigurationsoptionen überprüfen Sie sicher, dass die Vermeidung Sperren zu machen, wie beschrieben hier :

//myserver /mymount cifs username=*****,password=*****,iocharset=utf8,sec=ntlm,file,nolock,file_mode=0700,dir_mode=0700,uid=0500,gid=0500 0 0

Ich habe diese Fehler in einem Szenario ein wenig anders als die, die hier beschreiben.

Die SQLite-Datenbank auf einem NFS-Dateisystem ruhte von 3 Servern gemeinsam genutzt. Am 2. des Server konnte ich Abfragen in der Datenbank erfolgreich läuft, auf dem dritten dachte, dass ich immer die „Datenbank ist gesperrt“ Nachricht.

Die Sache mit dieser dritten Maschine war, dass es keinen Platz hatte, auf /var gelassen. Jedes Mal habe ich versucht, eine Abfrage in jeder SQLite-Datenbank läuft in diesem Dateisystem befindet ich bekam „Datenbank ist gesperrt“ Nachricht und auch diesen Fehler in den Protokollen:

  

8. August 10.33.38 server01 kernel: lockd: kann nicht überwachen 172.22.84.87

Und auch diese:

  

8. August 10.33.38 server01 rpc.statd [7430]: Fehler einzufügen: Schreiben /var/lib/nfs/statd/sm/other.server.name.com: Kein Platz auf dem Gerät links   8. August 10.33.38 server01 rpc.statd [7430]: STAT_FAIL server01 für SM_MON von 172.22.84.87

Nachdem die Raumsituation behandelt wurde alles bekam wieder normal.

Von Ihren vorherigen Kommentaren sagten, Sie eine -Journal Datei vorhanden ist.

Dies könnte bedeuten, dass Sie geöffnet und (EXCLUSIVE?) Transaktion und haben noch nicht die Daten verpflichtet. Hat Ihr Programm oder ein anderer Prozess die -Journal hinter ?? verlassen

Ein Neustart des SQLite-Prozess in der Journal-Datei aussehen wird und alle nicht bestätigten Aktionen bereinigen und entfernen Sie die -Journal Datei.

Wie Seun Osewa gesagt hat, manchmal ein Zombie-Prozess im Terminal mit einem Schloss aquired sitzen wird, auch wenn Sie es nicht für möglich. Ihr Skript ausgeführt wird, stürzt ab, und Sie gehen zurück auf die Eingabeaufforderung, aber es gibt einen Zombie-Prozess erzeugt irgendwo durch einen Bibliotheksaufruf, und dieser Prozess hat die Sperre.

Schließen des Terminal Sie waren (auf OSX) funktionieren könnte. Ein Neustart funktioniert. Sie könnten für „Python“ Prozesse aussehen (zum Beispiel), die nichts zu tun sind, und töten sie.

Sie können versuchen, diese: .timeout 100 Timeout zu setzen. Ich weiß nicht, was in der Kommandozeile passieren, aber in C # .Net, wenn ich dies tun: "UPDATE table-name SET column-name = value;" ich Datenbank ist gesperrt, aber die "UPDATE table-name SET column-name = value" es geht in Ordnung.

Es sieht aus, wie wenn man hinzufügen,, sqlite'll für weiteren Befehl aussieht

.

Ich habe diesen Fehler, wenn Delphi mit den LiteDAC Komponenten. Es stellte sich heraus geschah es nur während meine App aus dem Delphi IDE ausgeführt, wenn die Eigenschaft Connected wurde für die SQLite-Verbindungskomponente True festgelegt (in diesem Fall TLiteConnection).

Ich war mit "Datenbank ist gesperrt" Fehler in einer Multi-Thread-Anwendung als auch, was die SQLITE_BUSY Ergebniscode, und ich löste es mit der Einstellung sqlite3_busy_timeout etwas geeignet lange wie 30000.

(Auf einer Seite zur Kenntnis, wie seltsam, dass auf einer 7-jährigen Frage niemand dies bereits herausgefunden! SQLite ist wirklich ein besonderes und erstaunliches Projekt ...)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top