Pergunta

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

Como faço para desbloquear o banco de dados para que isso irá funcionar?

Foi útil?

Solução

No windows você pode tentar este programa http://www.nirsoft.net/utils/opened_files_view .html para descobrir o processo está a lidar com arquivo db. Tente fechado esse programa para banco de dados de desbloqueio

No Linux e MacOS que você pode fazer algo semelhante, por exemplo, se o seu arquivo bloqueado é development.db:

$ fusor development.db

Este comando irá mostrar o processo está bloqueando o arquivo:

> development.db: 5430

Apenas matar o processo ...

kill -9 5430

... E seu banco de dados será desbloqueado.

Outras dicas

Eu causei a minha db sqlite para tornar-se bloqueado por bater um aplicativo durante uma gravação. Aqui está como eu fixa-lo:

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

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

A página DatabaseIsLocked listados abaixo não está mais disponível. O arquivo de bloqueio e simultaneidade página descreve as alterações relacionadas com o bloqueio de arquivos introduzido em v3 e pode ser útil para futuros leitores. https://www.sqlite.org/lockingv3.html

Os SQLite wiki DatabaseIsLocked página oferece uma boa explicação sobre esta mensagem de erro . Afirma, em parte, que a fonte de disputa é interna (para o processo de emitir o erro).

Esta página não explica é como SQLite decide que algo em seu processo mantém um bloqueio e que condições poderia levar a um falso positivo.

Excluindo os sons de arquivo -Jornal como uma idéia terrível. Ele está lá para permitir sqlite para reverter o banco de dados para um estado consistente depois de um acidente. Se você apagá-lo, enquanto o banco de dados está em um estado inconsistente, então você é deixado com um banco de dados corrompido. Citando uma página do sqlite local :

Se uma perda de acidente ou de energia ocorre e um diário quente é deixado no disco, é essencial que o arquivo de banco de dados original e revista quente permanecem no disco com os nomes originais até que o arquivo de banco de dados é aberto por outro processo SQLite e rolou para trás. [...]

Nós suspeitamos que um modo de falha comum para a recuperação SQLite acontece assim: Uma falha de energia ocorre. Após a energia for restaurada, um usuário ou administrador de sistema bem-intencionado começa a olhar ao redor no disco para danos. Eles vêem o seu arquivo de banco de dados chamado "important.data". Este arquivo é talvez familiar para eles. Mas depois do acidente, há também um diário quente chamado "important.data-journal". O usuário, em seguida, exclui o diário quente, pensando que eles estão ajudando a limpar o sistema. Não conhecemos nenhuma maneira de evitar isso diferente de educação do usuário.

A reversão é suposto acontecer automaticamente na próxima vez que o banco de dados é aberto, mas falhará se o processo não pode bloquear o banco de dados. Como já foi dito, uma possível razão para isso é que outro processo tem atualmente aberto. Outra possibilidade é um bloqueio NFS obsoleto, se o banco de dados está em um volume NFS. Nesse caso, a solução é substituir o arquivo de banco de dados com uma nova cópia que não está bloqueado no servidor NFS (mv database.db original.db; cp original.db database.db). Note que o FAQ sqlite recomenda precaução quanto o acesso simultâneo aos bancos de dados em volumes NFS, por causa das implementações de buggy de NFS bloqueio de arquivos.

Eu não posso explicar por que excluir um arquivo -Jornal iria deixá-lo bloquear um banco de dados que você não podia antes. É que reprodutível?

A propósito, a presença de um arquivo -Jornal não significa necessariamente que houve um acidente ou que há mudanças para ser revertidas. Sqlite tem alguns modos de revistas diferentes, e em persistir ou modos TRUNCATE deixa o arquivo -Jornal no lugar sempre, e altera o conteúdo para indicar se há ou não transações parciais de reverter.

Se você quiser remover um erro "banco de dados está bloqueado", em seguida, siga estes passos:

  1. Copie o arquivo de banco de dados para outro local.
  2. Substitua o banco de dados com o banco de dados copiados. Isso vai excluir a referência de todos os processos que foram acessando seu arquivo de banco de dados.

Se um processo tem um bloqueio em um SQLite DB e cai, as estadias DB bloqueado permanentemente. Esse é o problema. Não é que algum outro processo tem um bloqueio.

os arquivos db SQLite são apenas arquivos, de modo que o primeiro passo seria a de se certificar de que não é só de leitura. A outra coisa a fazer é ter certeza de que você não tem algum tipo de GUI SQLite DB espectador com o aberto DB. Você poderia ter o DB abrir em outro shell, ou seu código pode ter a DB aberto. Normalmente você iria ver isso, se um segmento diferente, ou aplicativo, como SQLite Database Browser tem o DB aberto para escrita.

Eu tive esse problema agora mesmo, usando um banco de dados SQLite em um servidor remoto, armazenada em uma montagem NFS. SQLite não conseguiu obter um bloqueio após a sessão de shell remoto eu usei tinha deixado de funcionar, enquanto o banco de dados foi aberto.

As receitas de recuperação sugeridas acima não funcionou para mim (incluindo a idéia de primeiro movimento e, em seguida, copiar o banco de dados back). Mas depois copiá-lo para um sistema não-NFS, o banco de dados se tornou usável e não dados parece ter sido perdido.

Meu bloqueio foi causado pelo sistema falhe e não por um processo de suspensão. Para resolver isso, eu simplesmente renomeado o arquivo copiado-lo de volta ao nome original e localização do.

Usando um shell linux que seria ...

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

Eu adicionei "Pooling=true" a seqüência de conexão e funcionou.

Eu encontrei o documentação dos vários estados de bloqueio em SQLite para ser muito útil. Michael, se você pode executar lê, mas não pode realizar gravações para o banco de dados, o que significa que um processo tem obtido um bloqueio reservado no seu banco de dados, mas não executou a escrita ainda. Se você estiver usando SQLite3, há uma fechadura nova chamada PENDENTE onde não são permitidas mais processos para conectar mas as conexões existentes podem Sill realizar lê, por isso, se este é o problema que você deve olhar para que, em vez.

Este erro pode ser lançada se o arquivo está em uma pasta remota, como uma pasta compartilhada. Eu mudei o banco de dados para um diretório local e ele funcionou perfeitamente.

Eu tenho esse problema dentro do aplicativo, que o acesso ao SQLite a partir de 2 conexões - um foi somente leitura e outro para escrita e leitura. Parece que essa ligação só de leitura bloqueado escrito da segunda ligação. Finalmente, é Acontece que ele é necessário para finalizar ou, pelo menos, repor declarações preparadas imediatamente após o uso. Até declaração preparada é aberto, ele causou ao banco de dados foi bloqueado para a escrita.

NÃO SE ESQUEÇA DE CHAMADA:

sqlite_reset(xxx);

ou

sqlite_finalize(xxx);

Algumas funções, como INDEX'ing, pode levar um tempo muito longo - e bloqueia todo o banco de dados enquanto ele é executado. Em casos como esse, ele pode até não usar o arquivo de diário!

Portanto, a melhor / única maneira de verificar se o seu banco de dados está bloqueada porque um processo está ativamente escrevendo para ele (e, portanto, você deve deixá-lo em paz até a sua completou sua operação) é md5 (ou md5sum em alguns sistemas) o arquivo duas vezes. Se você receber uma soma de verificação diferente, o banco de dados está sendo escrito, e você realmente realmente realmente não quer kill -9 esse processo porque você pode facilmente acabar com uma tabela corrompida / banco de dados se o fizer.

Vou reiterar, porque é importante - a solução não é encontrar o programa de bloqueio e matá-lo - é para saber se o banco de dados tem um bloqueio de gravação por uma boa razão, e de lá ir. Às vezes, a solução correta é apenas uma pausa para o café.

A única maneira de criar esta bloqueado-mas-não-ser-escrito-a situação é se o seu programa é executado BEGIN EXCLUSIVE, porque queria fazer algumas alterações de mesa ou algo assim, então por que razão nunca envia um END depois, < strong> eo processo nunca termina . Todos os três condições sejam cumpridas é altamente improvável em qualquer código corretamente escrito, e como tal 99 vezes em 100 quando alguém quer matar -9 seu processo de bloqueio, o processo de bloqueio é realmente bloqueando o seu banco de dados para uma boa razão. Programadores não costumam adicionar a condição BEGIN EXCLUSIVE menos que eles realmente precisam, porque impede a concorrência e aumenta a reclamações dos usuários. SQLite si só adiciona-lo quando ele realmente precisa (como quando indexação).

Finalmente, o status 'bloqueado' não existe dentro do arquivo como várias respostas afirmaram - que reside no núcleo do sistema operacional. O processo que correu BEGIN EXCLUSIVE solicitou a partir do OS um bloqueio ser colocado no arquivo. Mesmo que o seu processo exclusivo caiu, seu sistema operacional será capaz de descobrir se ele deve manter o bloqueio de arquivo ou não !! Não é possível para acabar com uma base de dados que está bloqueado mas nenhum processo está bloqueando-o activamente !! Quando se trata de ver qual processo está bloqueando o arquivo, é normalmente melhor usar lsof em vez de fusor (esta é uma boa demonstração de por que: https://unix.stackexchange.com/questions/94316/fuser-vs-lsof-to-check-files-in-use ) . Alternativamente, se você tem DTrace (OSX) você pode usar iosnoop no arquivo.

Eu só tinha algo semelhante acontecer comigo - minha aplicação web foi capaz de ler a partir do banco de dados, mas não foi possível realizar quaisquer inserções ou atualizações. A reinicialização do Apache resolvido o problema, pelo menos temporariamente.

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

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

Este link resolver o problema. : Quando Sqlite dá: Base de dados bloqueado erro Ele resolveu o meu problema pode ser útil.

E você pode usar começar a transação e transação final para não fazer banco de dados bloqueado no futuro.

Deve ser problema interno de um banco de dados ...
Para mim, tem sido manifestado após tentar banco de dados de navegação com "gerente SQLite" ...
Então, se você não consegue encontrar outro processo se conectar ao banco de dados e você simplesmente não pode corrigi-lo, apenas tentar esta solução radical:

  1. Fornecer para exportar suas tabelas (Você pode usar "gerente SQLite" no Firefox)
  2. Se a migração alterar o seu esquema de banco de dados excluir a última migração falha
  3. Renomear o seu "database.sqlite" arquivo
  4. Executar "rake db: migrar" para fazer um novo banco de dados de trabalho
  5. Fornecer para dar as permissões corretas para banco de dados para importação de tabela
  6. Importe seus backup tabelas
  7. Escreva a nova migração
  8. executá-lo com "rake db:migrate"

Corri para este mesmo problema no Mac OS X 10.5.7 a execução de scripts Python em uma sessão de terminal. Mesmo que eu tinha parado os scripts e a janela do terminal estava sentado no prompt de comando, ele daria este erro da próxima vez que ele correu. A solução foi para fechar a janela de terminal e, em seguida, abri-lo novamente. Não faz sentido para mim, mas funcionou.

Eu só tinha o mesmo erro. Após 5 minets google-ing I, I didun't bruxa concha uma fechado foram utilizando o db. Basta fechá-lo e tente novamente;)

Eu tive o mesmo problema. Aparentemente, a função de reversão parece substituir o arquivo db com o jornal, que é o mesmo que o arquivo db mas sem a alteração mais recente. Eu tenho implementado isso no meu código abaixo e ele tem trabalhado muito bem desde então, enquanto que antes meu código seria apenas ficar preso no laço como o banco de dados ficou bloqueado.

Espero que isso 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 )

Uma razão comum para obter essa exceção é quando você está tentando fazer uma operação de gravação enquanto ainda mantém recursos para uma operação de leitura. Por exemplo, se você selecionar a partir de uma mesa, e depois tentar algo ATUALIZAÇÃO você selecionou sem fechar o ResultSet em primeiro lugar.

Antes de ir para baixo a opção de reinicialização, vale a pena para ver se você pode encontrar o usuário do banco de dados SQLite.

No Linux, pode-se empregar fuser para este fim:

$ fuser database.db

$ fuser database.db-journal

No meu caso eu tenho 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 pid 3556 (manage.py) usando o banco de dados.

Uma questão de idade, com um monte de respostas, aqui estão os passos que eu tenho seguido recentemente de ler as respostas acima, mas no meu caso, o problema foi devido a partilha de recursos CIFS. Este caso não é relatado anteriormente, por isso espero que ajude alguém.

  • Verifique há conexões são deixadas em aberto em seu código java.
  • Verifique nenhum outro processo está usando o arquivo db SQLite com lsof.
  • Verifique o proprietário do usuário do seu processo de JVM em execução tem r / w permissões sobre o arquivo.
  • Tente forçar o modo de bloqueio na abertura de ligação com

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

Se o seu usando seu arquivo db SQLite sobre uma pasta compartilhada NFS, verifique este ponto do FAQ SQLite, e rever suas opções de configuração de montagem para se certificar de seus bloqueios, evitando, como 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 descrever aqui.

O banco de dados SQLite descansou em um sistema de arquivos NFS compartilhada por 3 servidores. Em 2 dos servidores pude fazer consultas no banco de dados executado com êxito, no terceiro pensou que eu estava recebendo o "banco de dados está bloqueado" mensagem.

A coisa com este terceiro máquina era que não tinha espaço no /var. Toda vez que eu tentava executar uma consulta em qualquer banco de dados SQLite localizado nesta filesystem eu tenho o "banco de dados está bloqueado" mensagem e também este erro nos logs:

08 de agosto 10:33:38 núcleo server01: lockd: não pode monitorar 172.22.84.87

E este também:

08 de agosto 10:33:38 server01 rpc.statd [7430]: Falha ao inserir: Escrita /var/lib/nfs/statd/sm/other.server.name.com: Sem espaço no dispositivo 08 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 espaço foi tratadas tudo voltou ao normal.

De seus comentários anteriores você disse um arquivo -Jornal estava presente.

Isto poderia significar que você abriu e transação (EXCLUSIVE?) E ainda não ter cometido os dados. Será que o seu programa ou algum outro processo deixar a trás -Jornal ??

Reiniciar o processo sqlite vai olhar para o arquivo de diário e limpar quaisquer ações não confirmadas e remover o arquivo -Jornal.

Como Seun Osewa disse, às vezes um processo zumbi vai sentar-se no terminal com um bloqueio adquirido, mesmo se você não acho que seja possível. O script é executado, cai, e você voltar para o prompt, mas há um processo zumbi em algum lugar gerado por uma chamada de biblioteca, e esse processo tem a fechadura.

O encerramento do terminal estivesse num (a OSX) trabalho poder. Reiniciando vai funcionar. Você pode olhar para os processos "python" (por exemplo) que não estão fazendo nada, e matá-los.

Você pode tentar este: .timeout 100 definir o tempo limite. Eu não sei o que acontecerá em linha de comando, mas em C # .Net quando eu faço isso: "UPDATE table-name SET column-name = value;" eu recebo de banco de dados está bloqueado, mas isso "UPDATE table-name SET column-name = value" ele vai bem.

Parece que quando você adiciona;., Olhar sqlite'll para mais comando

Eu tenho esse erro ao usar Delphi com os componentes LiteDAC. Acabou por isso só aconteceu durante a execução meu aplicativo do Delphi IDE se a propriedade Connected foi definida True para o componente de conexão SQLite (neste caso TLiteConnection).

eu estava a ter "base de dados está bloqueado" erros de uma aplicação multi-roscado, assim, que parece ser o SQLITE_BUSY código de resultado, e eu resolvido com a criação sqlite3_busy_timeout para algo adequadamente longa como 30000.

(Em uma nota lateral, como estranho que em um de 7 anos pergunta ninguém descobriu isso já! SQLite realmente é um peculiar e projeto incrível ...)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top