Como faço para desbloquear um database SQLite?

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

Como faço para desbloquear o database para que isso funcione?

   

No Windows você pode tentar este programa http://www.nirsoft.net/utils/opened_files_view.html para descobrir o processo está lidando com o arquivo db. Tente fechar esse programa para desbloquear database

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:

> desenvolvimento.db: 5430

Apenas mate o processo …

matar -9 5430

… E seu database será desbloqueado.

Fiz com que meu database sqlite ficasse bloqueado ao travar um aplicativo durante uma gravação. Aqui está como eu consertei:

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

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

A página SQLite wiki DatabaseIsLocked oferece uma boa explicação sobre essa mensagem de erro. Afirma, em parte, que a fonte de contenção é interna (ao processo que emite o erro).

O que esta página não explica é como o SQLite decide que algo em seu processo contém um bloqueio e quais condições podem levar a um falso positivo.

Excluir o arquivo -jornal parece uma idéia terrível. Está lá para permitir que o sqlite reverta o database para um estado consistente após uma falha. Se você excluí-lo enquanto o database estiver em um estado inconsistente, você terá um database corrompido. Citando uma página do site sqlite :

Se ocorrer uma queda ou perda de energia e um diário quente for deixado no disco, é essencial que o arquivo de database original e o diário quente permaneçam no disco com seus nomes originais até que o arquivo de database seja aberto por outro processo SQLite e revertido . […]

Nós suspeitamos que um modo de falha comum para a recuperação de SQLite acontece assim: Ocorre uma falha de energia. Depois que a energia é restaurada, um usuário bem-intencionado ou administrador do sistema começa a procurar no disco por danos. Eles vêem seu arquivo de database chamado “important.data”. Este arquivo é talvez familiar para eles. Mas depois do acidente, há também uma revista quente chamada “important.data-journal”. O usuário então exclui o diário ativo, pensando que está ajudando a limpar o sistema. Não sabemos de nenhuma maneira de evitar isso, além da educação do usuário.

A reversão deve acontecer automaticamente na próxima vez que o database for aberto, mas falhará se o processo não puder travar o database. Como outros disseram, uma razão possível para isso é que outro processo atualmente está aberto. Outra possibilidade é um bloqueio de NFS antigo, se o database estiver em um volume NFS. Nesse caso, uma solução alternativa é replace o arquivo de database 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 o FAQ sqlite recomenda caucanvas em relação ao access simultâneo a bancos de dados em volumes NFS, devido a implementações com falhas do bloqueio de arquivos NFS.

Não consigo explicar por que excluir um arquivo -journal permitiria que você bloqueasse um database que não era possível antes. Isso é reproduzível?

A propósito, a presença de um arquivo -jornal não significa necessariamente que houve uma falha ou que existem mudanças a serem revertidas. O Sqlite possui alguns modos de diário diferentes, e nos modos PERSIST ou TRUNCATE, ele mantém sempre o arquivo -jornal e altera o conteúdo para indicar se há ou não transactions parciais para retroceder.

Se um processo tiver um bloqueio em um database SQLite e travar, o banco permanecerá permanentemente bloqueado. Esse é o problema. Não é que algum outro processo tenha um bloqueio.

Se você quiser remover um erro “o database está bloqueado”, siga estas etapas:

  1. Copie seu arquivo de database para algum outro local.
  2. Substitua o database pelo database copiado. Isto irá desreferenciar todos os processos que estavam acessando seu arquivo de database.

os arquivos db SQLite são apenas arquivos, então o primeiro passo seria garantir que não seja somente leitura. A outra coisa a fazer é ter certeza de que você não tem algum tipo de visualizador de SQLite GUI DB com o DB aberto. Você poderia ter o database aberto em outro shell, ou seu código pode ter o database aberto. Normalmente, você veria isso se um thread diferente, ou um aplicativo como o SQLite Database Browser, tivesse o DB aberto para gravação.

Eu tive esse problema agora, usando um database SQLite em um servidor remoto, armazenado em uma assembly NFS. O SQLite não conseguiu obter um bloqueio após a session do shell remoto que usei ter travado enquanto o database 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 database de volta). Mas depois de copiá-lo para um sistema não-NFS, o database tornou-se utilizável e os dados não parecem ter sido perdidos.

Eu achei a documentação dos vários estados de bloqueio no SQLite para ser muito útil. Michael, se você puder executar leituras, mas não puder executar gravações no database, isso significa que um processo obteve um bloqueio RESERVADO em seu database, mas ainda não executou a gravação. Se você estiver usando o SQLite3, há um novo bloqueio chamado PENDING, no qual nenhum outro processo pode se conectar, mas as conexões existentes podem realizar leituras, portanto, se esse for o problema, você deve examiná-lo.

Este erro pode ser lançado se o arquivo estiver em uma pasta remota, como uma pasta compartilhada. Eu mudei o database para um diretório local e funcionou perfeitamente.

Meu bloqueio foi causado pelo travamento do sistema e não por um processo de enforcamento. Para resolver isso, simplesmente renomeiei o arquivo e copiei de volta para o nome e localização originais.

Usando um shell linux que seria …

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

Eu tenho esse problema dentro do aplicativo, que o access ao SQLite a partir de 2 conexões – um era somente leitura e segundo para escrever e ler. Parece que a conexão somente leitura bloqueou a gravação da segunda conexão. Finalmente, verifica-se que é necessário finalizar ou, pelo menos, redefinir as declarações preparadas IMEDIATAMENTE após o uso. Até que a instrução preparada seja aberta, causou a base de dados foi bloqueada para escrever.

NÃO ESQUEÇA CHAMADA:

 sqlite_reset(xxx); 

ou

 sqlite_finalize(xxx); 

Algumas funções, como o INDEX, podem levar muito tempo – e bloqueia todo o database enquanto ele é executado. Em instâncias como essa, pode até não usar o arquivo de diário!

Portanto, a melhor / única maneira de verificar se o seu database está bloqueado porque um processo está escrevendo ACTIVAMENTE nele (e, portanto, você deve deixá-lo sozinho até que ele conclua sua operação) é md5 (ou md5sum em alguns sistemas) . Se você obtiver uma sum de verificação diferente, o database está sendo gravado e você realmente REALMENTE não quer matar -9 esse processo, porque você pode facilmente acabar com uma tabela / database corrompido se o fizer.

Vou reiterar, porque é importante – a solução NÃO é encontrar o programa de bloqueio e matá-lo – é descobrir se o database tem um bloqueio de gravação por um bom motivo e partir daí. Às vezes a solução correta é apenas um coffee break.

A única maneira de criar esta situação bloqueada, mas não sendo escrita, é se o seu programa executa o BEGIN EXCLUSIVE , porque ele queria fazer algumas alterações na tabela ou algo assim, por qualquer motivo, nunca envia um END depois, e o processo nunca termina . Todas as três condições encontradas são altamente improváveis ​​em qualquer código escrito corretamente e, como tal, 99 vezes em 100, quando alguém quer matar o processo de bloqueio, o processo de bloqueio bloqueia seu database por um bom motivo. Os programadores normalmente não adicionam a condição BEGIN EXCLUSIVE , a menos que realmente precisem, porque evitam a simultaneidade e aumentam as reclamações do usuário. O próprio SQLite apenas o adiciona quando realmente precisa (como quando indexa).

Finalmente, o status ‘bloqueado’ não existe no interior do arquivo, como várias respostas afirmaram – ele reside no kernel do sistema operacional. O processo que executou o BEGIN EXCLUSIVE solicitou ao SO que uma trava fosse colocada no arquivo. Mesmo que o seu processo exclusivo tenha caído, seu sistema operacional será capaz de descobrir se deve manter o bloqueio de arquivo ou não! Não é possível acabar com um database que está bloqueado, mas nenhum processo está bloqueando ativamente !! Quando se trata de ver qual processo está bloqueando o arquivo, normalmente é melhor usar lsof em vez de fuser (essa é uma boa demonstração do motivo: https://unix.stackexchange.com/questions/94316/fuser-vs-lsof- to-check-files-in-use ). Como alternativa, se você tiver o DTrace (OSX), poderá usar o iosnoop no arquivo.

Eu adicionei ” Pooling=true ” à string de conexão e funcionou.

Acabei de acontecer algo parecido comigo – meu aplicativo da Web pôde ler a partir do database, mas não pôde executar inserções ou atualizações. Uma reboot do Apache resolveu o problema pelo menos temporariamente.

Seria bom, no entanto, ser capaz de rastrear a causa raiz.

O comando lsof no meu ambiente Linux me ajudou a descobrir que um processo estava pendurado mantendo o arquivo aberto.
Matou o processo e o problema foi resolvido.

Este link resolve o problema. : Quando o Sqlite fornece: Erro de database bloqueado Ele resolveu que meu problema pode ser útil para você.

E você pode usar a transação inicial e a transação final para não tornar o database bloqueado no futuro.

Deve ser um problema interno do database …
Para mim, foi manifestado depois de tentar navegar no database com “Gerenciador de SQLite” …
Então, se você não consegue encontrar outro processo, conecte-se ao database e você não pode consertá-lo, apenas tente esta solução radical:

  1. Fornecer para exportar suas tabelas (Você pode usar o “Gerenciador de SQLite” no Firefox)
  2. Se a migration alterar seu esquema de database, exclua a última migration com falha
  3. Renomeie seu arquivo “database.sqlite”
  4. Execute “rake db: migrate” para criar um novo database de trabalho
  5. Fornecer para dar as permissions certas para o database para a importação da tabela
  6. Importar suas tabelas de backup
  7. Escreva a nova migration
  8. Execute-o com ” rake db:migrate

Eu me deparei com o mesmo problema no Mac OS X 10.5.7 executando scripts Python de uma session de terminal. Mesmo que eu tivesse parado os scripts e a janela do terminal estivesse no prompt de comando, ele forneceria esse erro na próxima vez que fosse executado. A solução foi fechar a janela do terminal e depois abri-la novamente. Não faz sentido para mim, mas funcionou.

Eu acabei de ter o mesmo erro. Após 5 minets do google-ing eu descobri que não fechei uma shell que estava usando o db. Apenas feche e tente novamente;)

Eu tive o mesmo problema. Aparentemente, a function de reversão parece sobrescrever o arquivo db com o 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 tem funcionado bem desde então, enquanto antes meu código só ficava preso no loop, pois o database permanecia bloqueado.

Espero que isto ajude

meu código 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 ) 

Um motivo comum para obter essa exceção é quando você está tentando fazer uma operação de gravação mantendo os resources para uma operação de leitura. Por exemplo, se você selecionar de uma tabela e, em seguida, tentar atualizar algo que você selecionou sem fechar seu ResultSet primeiro.

Antes de descer a opção de reboot, vale a pena verificar se você pode encontrar o usuário do database sqlite.

No Linux, pode-se empregar fuser para este 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 em Python com o pid 3556 (manage.py) usando o database.

Uma pergunta antiga, com muitas respostas, aqui estão os passos que eu tenho seguido recentemente lendo as respostas acima, mas no meu caso o problema foi devido ao compartilhamento de resources cifs. Este caso não é reportado anteriormente, então espere que ajude alguém.

  • Verifique se não há conexões deixadas abertas no seu código java.
  • Verifique se nenhum outro processo está usando seu arquivo db SQLite com lsof.
  • Verifique se o proprietário do usuário do seu processo jvm em execução possui permissions r / w sobre o arquivo.
  • Tente forçar o modo de bloqueio na abertura de 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 SQLb db em uma pasta compartilhada NFS, verifique este ponto da faq do SQLite e revise as opções de configuração de assembly para certificar-se de evitar os 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 tenho esse erro em um cenário um pouco diferente dos que descrevemos aqui.

O database SQLite estava em um sistema de arquivos NFS compartilhado por três servidores. Em 2 dos servidores eu consegui executar consultas no database com sucesso, no terceiro pensei que estava recebendo a mensagem “database is locked”.

A coisa com esta 3ª máquina era que ela não tinha espaço em /var . Toda vez que eu tentei executar uma consulta em qualquer database SQLite localizado neste sistema de arquivos eu tenho a mensagem “o database está bloqueado” e também este erro sobre os logs:

Aug 8 10:33:38 server01 kernel: lockd: não pode monitorar 172.22.84.87

E este também:

Aug 8 10:33:38 server01 rpc.statd [7430]: Falhou ao inserir: escrevendo /var/lib/nfs/statd/sm/other.server.name.com: Não há espaço disponível no dispositivo Aug 8 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 tratada, tudo voltou ao normal.

De seus comentários anteriores, você disse que um arquivo -jornal estava presente.

Isso pode significar que você abriu uma transação (EXCLUSIVA?) E ainda não confirmou os dados. Seu programa ou algum outro processo deixou o -jornal por trás?

Reiniciar o processo sqlite irá olhar para o arquivo de diário e limpar todas as ações não confirmadas e remover o arquivo -jornal.

Como Seun Osewa disse, às vezes um processo de zumbi fica no terminal com um bloqueio adquirido, mesmo que você não ache possível. Seu script é executado, falha e você retorna 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 reboot funcionará. Você poderia procurar por processos “python” (por exemplo) que não estão fazendo nada e matá-los.

você pode tentar isso: .timeout 100 para definir o tempo limite. Eu não sei o que acontece na linha de comando, mas em c # .net quando eu faço isso: "UPDATE table-name SET column-name = value;" Eu recebo database está bloqueado, mas este "UPDATE table-name SET column-name = value" vai bem.

Parece que quando você adiciona; o sqlite procurará mais comandos.

Eu recebi este erro ao usar o Delphi com os componentes do LiteDAC. Aconteceu que só aconteceu enquanto rodava meu aplicativo do IDE do Delphi se a propriedade Connected estivesse configurada como True para o componente de conexão do SQLite (neste caso, TLiteConnection).

Adminer é uma pequena (mas poderosa) alternativa de phpmyadmin que eu uso para monitorar o database sqlite. Por algum motivo, o database foi bloqueado. Aqui está como eu consertei.

  1. Eu baixei o arquivo sqlite para o meu sistema (FTP)
  2. Excluiu o arquivo sqlite on-line
  3. Carregou o arquivo de volta para o provedor de hospedagem

Isso funciona bem agora.