sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Come posso sbloccare il database in modo che funzioni?
sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Come posso sbloccare il database in modo che funzioni?
Risposte:
In Windows puoi provare questo programma http://www.nirsoft.net/utils/opened_files_view.html per scoprire che il processo sta gestendo il file db. Prova a chiudere quel programma per sbloccare il database
In Linux e macOS puoi fare qualcosa di simile, ad esempio, se il tuo file bloccato è development.db:
$ fuser development.db
Questo comando mostrerà quale processo sta bloccando il file:
> development.db: 5430
Basta uccidere il processo ...
uccidere -9 5430
... E il tuo database sarà sbloccato.
kill
dovrebbe andare bene, ma devi stare attento a ucciderlo correttamente, ed kill -9
è probabilmente sbagliato e / o eccessivo. Se il processo viene sospeso e non morirà altrimenti, a volte è necessario kill -9
. Ma non vuoi andare a uccidere il lavoro di produzione principale solo per poter segnalare che il database non è più bloccato!
Ho causato il blocco del mio db sqlite bloccando un'app durante una scrittura. Ecco come l'ho risolto:
echo ".dump" | sqlite old.db | sqlite new.db
Tratto da: 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 pagina DatabaseIsLocked elencata di seguito non è più disponibile. La pagina Blocco e concorrenza dei file descrive le modifiche relative al blocco dei file introdotte nella v3 e può essere utile per i lettori futuri.https://www.sqlite.org/lockingv3.html
Il SQLite wiki DatabaseIsLocked pagina offre una buona spiegazione di questo messaggio di errore. Indica, in parte, che la fonte della contesa è interna (al processo che emette l'errore).
Ciò che questa pagina non spiega è come SQLite decide che qualcosa nel tuo processo ha un blocco e quali condizioni potrebbero portare a un falso positivo.
L'eliminazione del file -journal sembra un'idea terribile. È lì per consentire a sqlite di ripristinare il database in uno stato coerente dopo un arresto anomalo. Se lo elimini mentre il database si trova in uno stato incoerente, rimarrai con un database danneggiato. Citando una pagina dal sito sqlite :
Se si verifica un arresto anomalo o un'interruzione dell'alimentazione e un disco caldo viene lasciato sul disco, è essenziale che il file del database originale e il giornale caldo rimangano sul disco con i loro nomi originali fino a quando il file del database non viene aperto da un altro processo SQLite e ripristinato . [...]
Sospettiamo che si verifichi una modalità di errore comune per il recupero di SQLite in questo modo: si verifica un'interruzione di corrente. Dopo il ripristino dell'alimentazione, un utente o un amministratore di sistema ben intenzionato inizia a cercare danni sul disco. Vedono il loro file di database chiamato "important.data". Questo file è forse familiare a loro. Ma dopo l'incidente, c'è anche un diario caldo chiamato "important.data-journal". L'utente quindi elimina il journal caldo, pensando che sta aiutando a ripulire il sistema. Non conosciamo alcun modo per impedirlo se non la formazione degli utenti.
Il rollback dovrebbe avvenire automaticamente alla successiva apertura del database, ma non riuscirà se il processo non è in grado di bloccare il database. Come altri hanno già detto, una possibile ragione di ciò è che un altro processo attualmente lo ha aperto. Un'altra possibilità è un blocco NFS non aggiornato, se il database si trova su un volume NFS. In tal caso, una soluzione alternativa consiste nel sostituire il file di database con una nuova copia non bloccata sul server NFS (mv database.db original.db; cp original.db database.db). Si noti che le FAQ di sqlite raccomandano cautela riguardo all'accesso simultaneo ai database sui volumi NFS, a causa delle implementazioni errate del blocco dei file NFS.
Non riesco a spiegare perché la cancellazione di un file -journal ti permetterebbe di bloccare un database che prima non potevi. È riproducibile?
A proposito, la presenza di un file -journal non significa necessariamente che si sia verificato un arresto anomalo o che ci siano modifiche da ripristinare. Sqlite ha alcune diverse modalità journal e nelle modalità PERSIST o TRUNCATE lascia sempre il file -journal in atto e cambia il contenuto per indicare se ci sono o meno transazioni parziali da ripristinare.
Se si desidera rimuovere un errore "il database è bloccato", attenersi alla seguente procedura:
Se un processo ha un blocco su un DB SQLite e si arresta in modo anomalo, il DB rimane bloccato in modo permanente. Questo è il problema. Non è che qualche altro processo abbia un lucchetto.
i file db di SQLite sono solo file, quindi il primo passo sarebbe assicurarsi che non sia di sola lettura. L'altra cosa da fare è assicurarsi di non avere una sorta di visualizzatore di SQLite DB GUI con il DB aperto. È possibile che il DB sia aperto in un'altra shell oppure il codice potrebbe avere il DB aperto. In genere si vedrebbe questo se un thread diverso o un'applicazione come SQLite Database Browser ha il DB aperto per la scrittura.
Ho avuto questo problema proprio ora, usando un database SQLite su un server remoto, archiviato su un mount NFS. SQLite non è stato in grado di ottenere un blocco dopo l'arresto anomalo della sessione di shell remota che ho usato mentre il database era aperto.
Le ricette per il recupero suggerite sopra non hanno funzionato per me (inclusa l'idea di spostare prima e quindi copiare nuovamente il database). Ma dopo averlo copiato su un sistema non NFS, il database è diventato utilizzabile e non sembra che i dati siano andati persi.
Il mio blocco è stato causato dal crash del sistema e non da un processo sospeso. Per risolvere questo, ho semplicemente rinominato il file e poi l'ho copiato nel nome e nella posizione originali.
Utilizzando una shell Linux che sarebbe ...
mv mydata.db temp.db
cp temp.db mydata.db
Ho aggiunto " Pooling=true
" alla stringa di connessione e ha funzionato.
Ho trovato molto utile la documentazione dei vari stati di blocco in SQLite. Michael, se è possibile eseguire letture ma non è possibile eseguire scritture nel database, ciò significa che un processo ha ottenuto un blocco RISERVATO sul database ma non ha ancora eseguito la scrittura. Se stai usando SQLite3, c'è un nuovo blocco chiamato PENDING in cui non è più possibile connettere più processi ma le connessioni esistenti possono eseguire le letture, quindi se questo è il problema dovresti invece esaminarlo.
Ho un tale problema all'interno dell'app, che accede a SQLite da 2 connessioni: una era di sola lettura e la seconda per la scrittura e la lettura. Sembra che quella connessione di sola lettura abbia bloccato la scrittura dalla seconda connessione. Infine, si scopre che è necessario finalizzare o, almeno, ripristinare le istruzioni preparate IMMEDIATAMENTE dopo l'uso. Fino all'apertura dell'istruzione preparata, il database è stato bloccato per la scrittura.
NON DIMENTICARE LA CHIAMATA:
sqlite_reset(xxx);
o
sqlite_finalize(xxx);
Alcune funzioni, come INDEX, possono richiedere molto tempo e blocca l'intero database mentre è in esecuzione. In casi del genere, potrebbe anche non utilizzare il file journal!
Quindi il modo migliore / unico per verificare se il tuo database è bloccato perché un processo sta ATTIVAMENTE scrivendo su di esso (e quindi dovresti lasciarlo da solo fino a quando non ha completato il suo funzionamento) è md5 (o md5sum su alcuni sistemi) il file due volte . Se si ottiene un checksum diverso, il database è in fase di scrittura e in realtà non si vuole davvero uccidere -9 quel processo perché si può facilmente finire con una tabella / database corrotto se lo si fa.
Lo ripeterò, perché è importante - la soluzione NON è trovare il programma di blocco e ucciderlo - è scoprire se il database ha un blocco di scrittura per una buona ragione, e andare da lì. A volte la soluzione corretta è solo una pausa caffè.
L'unico modo per creare questa situazione bloccata ma non scritta è se il tuo programma viene eseguito BEGIN EXCLUSIVE
, perché voleva fare alcune modifiche alla tabella o qualcosa del genere, quindi per qualsiasi motivo non invia mai un END
dopo, e il processo non termina mai . Tutte e tre le condizioni soddisfatte sono altamente improbabili in qualsiasi codice scritto correttamente, e come tale 99 volte su 100 quando qualcuno vuole uccidere -9 il loro processo di blocco, il processo di blocco sta effettivamente bloccando il database per una buona ragione. I programmatori in genere non aggiungono la BEGIN EXCLUSIVE
condizione a meno che non ne abbiano davvero bisogno, perché impedisce la concorrenza e aumenta i reclami degli utenti. Lo stesso SQLite lo aggiunge solo quando è realmente necessario (come durante l'indicizzazione).
Infine, lo stato "bloccato" non esiste all'interno del file, come indicato da diverse risposte, risiede nel kernel del sistema operativo. Il processo eseguito BEGIN EXCLUSIVE
ha richiesto al sistema operativo di inserire un blocco nel file. Anche se il tuo processo esclusivo è andato in crash, il tuo sistema operativo sarà in grado di capire se deve mantenere il blocco dei file o no !! Non è possibile finire con un database bloccato ma nessun processo lo sta bloccando attivamente !! Quando si tratta di vedere quale processo sta bloccando il file, in genere è meglio usare lsof piuttosto che fuser (questa è una buona dimostrazione del perché: /unix/94316/fuser-vs-lsof- per controllare i file in uso ). In alternativa, se si dispone di DTrace (OSX), è possibile utilizzare iosnoop sul file.
Mi è appena successo qualcosa di simile: la mia applicazione Web è stata in grado di leggere dal database, ma non è stato in grado di eseguire inserimenti o aggiornamenti. Un riavvio di Apache ha risolto il problema almeno temporaneamente.
Sarebbe bello, tuttavia, essere in grado di rintracciare la causa principale.
Questo link risolve il problema. : Quando Sqlite dà: Errore di blocco del database Risolto il mio problema potrebbe esservi utile.
Inoltre, è possibile utilizzare la transazione di inizio e fine per non bloccare il database in futuro.
Dovrebbe essere un problema interno di un database ...
Per me si è manifestato dopo aver cercato di sfogliare il database con "Gestione SQLite" ...
Quindi, se non riesci a trovare un altro processo connettiti al database e non puoi risolverlo, prova questa soluzione radicale:
rake db:migrate
"Ho riscontrato questo stesso problema su Mac OS X 10.5.7 eseguendo script Python da una sessione terminale. Anche se avevo interrotto gli script e la finestra del terminale era seduta al prompt dei comandi, alla successiva esecuzione avrebbe restituito questo errore. La soluzione era chiudere la finestra del terminale e quindi riaprirla. Non ha senso per me, ma ha funzionato.
Ho avuto lo stesso problema. Apparentemente la funzione di rollback sembra sovrascrivere il file db con il journal che è lo stesso del file db ma senza la modifica più recente. Ho implementato questo nel mio codice qui sotto e ha funzionato benissimo da allora, mentre prima il mio codice si sarebbe bloccato nel loop mentre il database rimaneva bloccato.
Spero che questo ti aiuti
##############
#### 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 )
Un motivo comune per ottenere questa eccezione è quando si sta tentando di eseguire un'operazione di scrittura mentre si mantengono ancora le risorse per un'operazione di lettura. Ad esempio, se si SELEZIONA da una tabella e quindi si tenta di AGGIORNARE qualcosa che è stato selezionato senza chiudere prima il ResultSet.
Stavo riscontrando errori di "database bloccato" anche in un'applicazione multi-thread, che sembra essere il codice risultato SQLITE_BUSY e l'ho risolto con l'impostazione sqlite3_busy_timeout su qualcosa di adeguatamente lungo come 30000.
(A proposito, che strano che su una domanda di 7 anni nessuno lo abbia già scoperto! SQLite è davvero un progetto singolare e sorprendente ...)
Prima di disattivare l'opzione di riavvio, vale la pena vedere se è possibile trovare l'utente del database sqlite.
Su Linux, si può impiegare fuser
a tal fine:
$ fuser database.db
$ fuser database.db-journal
Nel mio caso ho ottenuto la seguente risposta:
philip 3556 4700 0 10:24 pts/3 00:00:01 /usr/bin/python manage.py shell
Il che ha dimostrato che avevo un altro programma Python con pid 3556 (manage.py) usando il database.
Una vecchia domanda, con molte risposte, ecco i passaggi che ho seguito recentemente leggendo le risposte sopra, ma nel mio caso il problema era dovuto alla condivisione delle risorse cifs. Questo caso non è stato segnalato in precedenza, quindi spero che aiuti qualcuno.
Prova a forzare la modalità di blocco sull'apertura della connessione con
final SQLiteConfig config = new SQLiteConfig();
config.setReadOnly(false);
config.setLockingMode(LockingMode.NORMAL);
connection = DriverManager.getConnection(url, config.toProperties());
Se stai usando il tuo file db di SQLite su una cartella condivisa NFS, controlla questo punto della domanda SQLite e rivedi le opzioni di configurazione di montaggio per assicurarti di evitare i blocchi, come descritto qui :
//myserver /mymount cifs username=*****,password=*****,iocharset=utf8,sec=ntlm,file,nolock,file_mode=0700,dir_mode=0700,uid=0500,gid=0500 0 0
Ho riscontrato questo errore in uno scenario un po 'diverso da quelli descritti qui.
Il database SQLite si basava su un filesystem NFS condiviso da 3 server. Su 2 dei server sono stato in grado di eseguire correttamente le query sul database, mentre il terzo pensava di ricevere il messaggio "il database è bloccato".
La cosa con questa terza macchina era che non aveva più spazio /var
. Ogni volta che ho provato a eseguire una query in QUALSIASI database SQLite situato in questo filesystem ho ricevuto il messaggio "il database è bloccato" e anche questo errore sui registri:
8 agosto 10:33:38 kernel server01: lockd: impossibile monitorare 172.22.84.87
E anche questo:
8 agosto 10:33:38 server01 rpc.statd [7430]: impossibile inserire: writing /var/lib/nfs/statd/sm/other.server.name.com: spazio non disponibile sul dispositivo 8 agosto 10:33: 38 server01 rpc.statd [7430]: STAT_FAIL su server01 per SM_MON di 172.22.84.87
Dopo che la situazione spaziale è stata gestita, tutto è tornato alla normalità.
Se stai provando a sbloccare il database Chrome per visualizzarlo con SQLite , devi semplicemente chiudere Chrome.
finestre
%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
Dai tuoi commenti precedenti hai detto che era presente un file -journal.
Ciò potrebbe significare che hai aperto e (ESCLUSIVO?) Transazione e non hai ancora eseguito il commit dei dati. Il tuo programma o qualche altro processo ha lasciato indietro il -journal ??
Il riavvio del processo sqlite esaminerà il file journal e pulirà tutte le azioni non impegnate e rimuoverà il file -journal.
Come ha detto Seun Osewa, a volte un processo di zombi siederà nel terminale con una serratura acquisita, anche se non lo pensi possibile. Lo script viene eseguito, si arresta in modo anomalo e si ritorna al prompt, ma esiste un processo di zombi generato da qualche parte da una chiamata in libreria e quel processo ha il blocco.
La chiusura del terminale in cui ci si trovava (su OSX) potrebbe funzionare. Il riavvio funzionerà. Potresti cercare processi "python" (per esempio) che non stanno facendo nulla e ucciderli.
puoi provare questo: .timeout 100
per impostare il timeout. Non so cosa succede nella riga di comando, ma in C # .Net quando faccio questo: "UPDATE table-name SET column-name = value;"
Ottengo Database bloccato ma questo "UPDATE table-name SET column-name = value"
va bene.
Sembra che quando si aggiunge; sqlite cercherà ulteriori comandi.