sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Como desbloquear o banco de dados para que isso funcione?
sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Como desbloquear o banco de dados para que isso funcione?
Respostas:
No Windows, você pode tentar este programa http://www.nirsoft.net/utils/opened_files_view.html para descobrir que o processo está lidando com o arquivo db. Tente fechar esse programa para desbloquear o banco de dados
No Linux e no macOS, você pode fazer algo semelhante, por exemplo, se o arquivo bloqueado for development.db:
$ fuser development.db
Este comando mostrará qual processo está bloqueando o arquivo:
> development.db: 5430
Basta matar o processo ...
kill -9 5430
... E seu banco de dados será desbloqueado.
kill
, tudo bem, mas você deve ter cuidado para matá-lo adequadamente e kill -9
provavelmente está errado e / ou exagero. Se o processo for interrompido e não morrerá, às vezes você precisa kill -9
. Mas você não deseja interromper o trabalho principal de produção apenas para poder relatar que o banco de dados não está mais bloqueado!
Fiz com que meu sqlite db ficasse bloqueado ao travar um aplicativo durante uma gravação. Aqui está como eu o consertei:
echo ".dump" | sqlite old.db | sqlite new.db
Retirado 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)
A página DatabaseIsLocked listada abaixo não está mais disponível. A página Bloqueio de arquivo e simultaneidade descreve as alterações relacionadas ao bloqueio de arquivo introduzidas na v3 e podem ser úteis para futuros leitores.https://www.sqlite.org/lockingv3.html
O wiki DatabaseiteLocked do SQLite página oferece uma boa explicação para essa mensagem de erro. Ele afirma, em parte, que a fonte da disputa é interna (ao processo que emite o erro).
O que esta página não explica é como o SQLite decide que algo em seu processo possui um bloqueio e que condições podem levar a um falso positivo.
Excluir o arquivo -journal parece uma péssima idéia. Está lá para permitir ao sqlite reverter o banco de dados para um estado consistente após uma falha. Se você o excluir enquanto o banco de dados estiver em um estado inconsistente, ficará com um banco de dados corrompido. Citando uma página do site sqlite :
Se ocorrer uma falha ou perda de energia e um hot journal for deixado no disco, é essencial que o arquivo de banco de dados original e o hot journal permaneçam no disco com seus nomes originais até que o arquivo de banco de dados seja aberto por outro processo SQLite e revertido . [...]
Suspeitamos que um modo de falha comum para recuperação do SQLite ocorra da seguinte maneira: Ocorre uma falha de energia. Após a restauração da energia, um usuário bem-intencionado ou administrador do sistema começa a procurar danos no disco. Eles veem o arquivo de banco de dados chamado "important.data". Esse arquivo talvez seja familiar para eles. Mas após o acidente, também existe um diário ativo chamado "important.data-journal". O usuário exclui o diário ativo, pensando que está ajudando a limpar o sistema. Não sabemos como evitar isso além da educação do usuário.
A reversão deve ocorrer automaticamente na próxima vez que o banco de dados for aberto, mas falhará se o processo não puder bloquear o banco de dados. Como outros já disseram, uma possível razão para isso é que outro processo está aberto no momento. Outra possibilidade é um bloqueio NFS antigo, se o banco de dados estiver em um volume NFS. Nesse caso, uma solução alternativa é substituir o arquivo do banco de dados por uma nova cópia que não esteja bloqueada no servidor NFS (mv database.db original.db; cp original.db database.db). Observe que as perguntas frequentes do sqlite recomendam cautela em relação ao acesso simultâneo a bancos de dados em volumes NFS, devido a implementações com erros do bloqueio de arquivos NFS.
Não sei explicar por que excluir um arquivo -journal permitiria bloquear um banco de dados que não era possível antes. Isso é reproduzível?
A propósito, a presença de um arquivo -journal não significa necessariamente que houve uma falha ou que há mudanças a serem revertidas. O Sqlite possui alguns modos de diário diferentes e, nos modos PERSIST ou TRUNCATE, deixa sempre o arquivo -journal no lugar e altera o conteúdo para indicar se há transações parciais para reverter ou não.
Se você deseja remover um erro "o banco de dados está bloqueado", siga estas etapas:
Se um processo tiver um bloqueio em um banco de dados SQLite e falhar, o banco de dados permanecerá bloqueado permanentemente. Esse é o problema. Não é que algum outro processo tenha um bloqueio.
os arquivos db SQLite são apenas arquivos, portanto, o primeiro passo seria garantir que não seja somente leitura. A outra coisa a fazer é garantir que você não tenha algum tipo de visualizador de SQLite DB da GUI com o DB aberto. Você pode ter o banco de dados aberto em outro shell ou seu código pode ter o banco de dados aberto. Normalmente, você veria isso se um thread ou aplicativo diferente, como o SQLite Database Browser, tivesse o banco de dados aberto para gravação.
Eu tive esse problema agora, usando um banco de dados SQLite em um servidor remoto, armazenado em uma montagem NFS. O SQLite não conseguiu obter um bloqueio após a falha da sessão do shell remoto que usei enquanto o banco de dados estava aberto.
As receitas de recuperação sugeridas acima não funcionaram para mim (incluindo a idéia de primeiro mover e depois copiar o banco de dados). Mas, depois de copiá-lo para um sistema não NFS, o banco de dados se tornou utilizável e não parece que os dados foram perdidos.
Meu bloqueio foi causado pelo travamento do sistema e não por um processo interrompido. Para resolver isso, simplesmente renomeei o arquivo e o copiei novamente para o nome e localização originais.
Usando um shell linux que seria ...
mv mydata.db temp.db
cp temp.db mydata.db
Eu adicionei " Pooling=true
" à string de conexão e funcionou.
Achei a documentação dos vários estados de bloqueio no SQLite muito útil. Michael, se você pode executar leituras, mas não pode executar gravações no banco de dados, isso significa que um processo obteve um bloqueio RESERVADO no banco de dados, mas ainda não executou a gravação. Se você estiver usando o SQLite3, há um novo bloqueio chamado PENDING, no qual não são permitidos mais processos, mas as conexões existentes podem ainda executar leituras; portanto, se esse for o problema, você deve examinar isso.
Eu tenho esse problema dentro do aplicativo, que acessa o SQLite a partir de 2 conexões - uma era somente leitura e a segunda para gravação e leitura. Parece que a conexão somente leitura bloqueou a gravação da segunda conexão. Por fim, verifica-se que é necessário finalizar ou, pelo menos, redefinir as instruções preparadas IMEDIATAMENTE após o uso. Até que a instrução preparada seja aberta, ela causou um bloqueio no banco de dados para gravação.
NÃO ESQUEÇA DE CHAMAR:
sqlite_reset(xxx);
ou
sqlite_finalize(xxx);
Algumas funções, como INDEX'ing, podem demorar muito tempo - e bloqueiam todo o banco de dados enquanto ele é executado. Em casos como esse, talvez nem use o arquivo de diário!
Portanto, a melhor / única maneira de verificar se o seu banco de dados está bloqueado porque um processo está gravando ATIVAMENTE (e, portanto, você deve deixá-lo em paz até a conclusão de sua operação) é no md5 (ou md5sum em alguns sistemas) o arquivo duas vezes . Se você obtiver uma soma de verificação diferente, o banco de dados está sendo gravado e, na verdade, você REALMENTE NÃO deseja matar -9 nesse processo, pois pode acabar facilmente com uma tabela / banco de dados corrompidos.
Vou reiterar, porque é importante - a solução NÃO é encontrar o programa de bloqueio e matá-lo - é descobrir se o banco de dados possui um bloqueio de gravação por um bom motivo, e partir daí. Às vezes, a solução correta é apenas uma pausa para o café.
A única maneira de criar essa situação bloqueada, mas não sendo gravada é se o seu programa for executado BEGIN EXCLUSIVE
, porque ele queria fazer algumas alterações na tabela ou algo assim, então, por qualquer motivo, nunca envia END
depois e o processo nunca termina . Todas as três condições atendidas são altamente improváveis em qualquer código corretamente escrito e, como tal, 99 vezes em 100 quando alguém deseja matar -9 seu processo de bloqueio, o processo de bloqueio está realmente bloqueando seu banco de dados por um bom motivo. Os programadores normalmente não adicionam a BEGIN EXCLUSIVE
condição, a menos que realmente precisem, porque isso impede a concorrência e aumenta as reclamações dos usuários. O próprio SQLite o adiciona apenas quando realmente é necessário (como na indexação).
Finalmente, o status 'bloqueado' não existe DENTRO do arquivo, como várias respostas indicaram - ele reside no kernel do sistema operacional. O processo executado BEGIN EXCLUSIVE
solicitou ao sistema operacional um bloqueio para ser colocado no arquivo. Mesmo que seu processo exclusivo tenha falhado, seu sistema operacional será capaz de descobrir se deve manter o bloqueio do arquivo ou não !! Não é possível terminar com um banco de dados bloqueado, mas nenhum processo está bloqueando-o ativamente! Quando se trata de ver qual processo está bloqueando o arquivo, normalmente é melhor usar lsof do que o fusor (esta é uma boa demonstração do porquê: /unix/94316/fuser-vs-lsof- para verificar os arquivos em uso ). Como alternativa, se você possui o DTrace (OSX), pode usar o iosnoop no arquivo.
Acabei de acontecer algo parecido comigo - meu aplicativo da Web conseguiu ler o banco de dados, mas não conseguiu realizar inserções ou atualizações. Uma reinicialização do Apache resolveu o problema pelo menos temporariamente.
Seria bom, no entanto, ser capaz de rastrear a causa raiz.
Este link resolve o problema. : Quando o Sqlite fornece: Erro de bloqueio do banco de dados Ele resolveu meu problema pode ser útil para você.
E você pode usar a transação inicial e a transação final para não bloquear o banco de dados no futuro.
Deve ser um problema interno do banco de dados ...
Para mim, ele se manifestou depois de tentar navegar no banco de dados com o "SQLite manager" ...
Então, se você não encontrar outro processo, conecte-se ao banco de dados e não consiga corrigi-lo, tente esta solução radical:
rake db:migrate
"Eu encontrei esse mesmo problema no Mac OS X 10.5.7 executando scripts Python a partir de uma sessão do terminal. Mesmo que eu tivesse parado os scripts e a janela do terminal estivesse no prompt de comando, isso causaria esse erro na próxima vez em que fosse executado. A solução foi fechar a janela do terminal e abri-la novamente. Não faz sentido para mim, mas funcionou.
Eu tive o mesmo problema. Aparentemente, a função de reversão parece substituir o arquivo db pelo diário, que é o mesmo que o arquivo db, mas sem a alteração mais recente. Eu implementei isso no meu código abaixo e ele está funcionando bem desde então, enquanto antes meu código ficava preso no loop enquanto o banco de dados fica bloqueado.
Espero que isto ajude
##############
#### 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 )
Um motivo comum para obter essa exceção é quando você está tentando executar uma operação de gravação enquanto mantém os recursos para uma operação de leitura. Por exemplo, se você selecionar a partir de uma tabela e tentar atualizar algo que você selecionou sem fechar primeiro o ResultSet.
Eu também estava tendo erros "o banco de dados está bloqueado" em um aplicativo multithread, que parece ser o código de resultado SQLITE_BUSY , e resolvi-o com a configuração de sqlite3_busy_timeout para algo adequadamente longo como 30000.
(Em uma nota lateral, como é estranho que em uma pergunta de 7 anos ninguém tenha descoberto isso! SQLite é realmente um projeto peculiar e surpreendente ...)
Antes de ir para a opção de reinicialização, vale a pena ver se você encontra o usuário do banco de dados sqlite.
No Linux, pode-se empregar fuser
para esse fim:
$ fuser database.db
$ fuser database.db-journal
No meu caso, recebi a seguinte resposta:
philip 3556 4700 0 10:24 pts/3 00:00:01 /usr/bin/python manage.py shell
O que mostrou que eu tinha outro programa Python com o pid 3556 (manage.py) usando o banco de dados.
Uma pergunta antiga, com muitas respostas, eis as etapas que segui recentemente, lendo as respostas acima, mas, no meu caso, o problema ocorreu devido ao compartilhamento de recursos CIFs. Este caso não foi relatado anteriormente, por isso espero que ajude alguém.
Tente forçar o modo de bloqueio na abertura da conexão com
final SQLiteConfig config = new SQLiteConfig();
config.setReadOnly(false);
config.setLockingMode(LockingMode.NORMAL);
connection = DriverManager.getConnection(url, config.toProperties());
Se você estiver usando o arquivo db SQLite em uma pasta compartilhada NFS, verifique este ponto do faq do SQLite e revise suas opções de configuração de montagem para garantir que você evite bloqueios, conforme descrito aqui :
//myserver /mymount cifs username=*****,password=*****,iocharset=utf8,sec=ntlm,file,nolock,file_mode=0700,dir_mode=0700,uid=0500,gid=0500 0 0
Eu recebi esse erro em um cenário um pouco diferente dos descritos aqui.
O banco de dados SQLite estava em um sistema de arquivos NFS compartilhado por 3 servidores. Em dois dos servidores, eu era capaz de executar consultas no banco de dados com êxito, no terceiro, pensei que estava recebendo a mensagem "o banco de dados está bloqueado".
A coisa com esta terceira máquina era que ela não tinha mais espaço /var
. Toda vez que eu tentava executar uma consulta em QUALQUER banco de dados SQLite localizado neste sistema de arquivos, recebia a mensagem "o banco de dados está bloqueado" e também esse erro nos logs:
8 de agosto 10:33:38 kernel server01: lockd: não pode monitorar 172.22.84.87
E este também:
8 de agosto 10:33:38 server01 rpc.statd [7430]: Falha ao inserir: writing /var/lib/nfs/statd/sm/other.server.name.com: Não há espaço no dispositivo 8 de agosto 10:33: 38 server01 rpc.statd [7430]: STAT_FAIL para server01 para SM_MON de 172.22.84.87
Depois que a situação espacial foi resolvida, tudo voltou ao normal.
Se você estiver tentando desbloquear o banco de dados do Chrome para visualizá-lo com o SQLite , basta desligar o Chrome.
janelas
%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
Dos seus comentários anteriores, você disse que um arquivo -journal estava presente.
Isso pode significar que você abriu e (EXCLUSIVO?) A transação e ainda não confirmou os dados. Seu programa ou algum outro processo deixou o diário para trás?
Reiniciar o processo sqlite examinará o arquivo de diário, limpará as ações não confirmadas e removerá o arquivo -journal.
Como Seun Osewa disse, às vezes um processo de zumbi fica no terminal com uma trava, mesmo que você não considere possível. Seu script é executado, trava e você volta ao prompt, mas há um processo de zumbi gerado em algum lugar por uma chamada de biblioteca, e esse processo tem o bloqueio.
Fechar o terminal em que você estava (no OSX) pode funcionar. A reinicialização funcionará. Você pode procurar por processos "python" (por exemplo) que não estão fazendo nada e matá-los.
você pode tentar o seguinte: .timeout 100
para definir o tempo limite. Não sei o que acontece na linha de comando, mas no C # .Net quando faço isso: "UPDATE table-name SET column-name = value;"
Recebo o banco de dados bloqueado, mas isso funciona "UPDATE table-name SET column-name = value"
bem.
Parece que quando você adiciona ;, o sqlite procurará mais comandos.