¿Cómo deslocking una base de datos SQLite?

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

¿Cómo deslocking la base de datos para que funcione?

En Windows, puede probar este progtwig http://www.nirsoft.net/utils/opened_files_view.html para descubrir que el proceso está manejando el archivo db. Intente cerrar ese progtwig para desbloquear la base de datos

En Linux y macOS puede hacer algo similar, por ejemplo, si su archivo bloqueado es development.db:

$ fuser development.db

Este comando mostrará qué proceso está bloqueando el archivo:

> desarrollo.db: 5430

Solo mata el proceso …

matar -9 5430

… Y tu base de datos estará desbloqueada.

Hice que mi sqlite db se bloqueara al bloquear una aplicación durante una escritura. Así es como lo arreglé:

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

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

La página DatabaseIsLocked de SQLite wiki ofrece una buena explicación de este mensaje de error. Establece, en parte, que la fuente de contención es interna (al proceso que emite el error).

Lo que esta página no explica es cómo SQLite decide que algo en su proceso mantiene un locking y qué condiciones pueden llevar a un falso positivo.

Eliminar el archivo -journal suena como una idea terrible. Está ahí para permitir que sqlite retrotraiga la base de datos a un estado consistente después de un locking. Si lo elimina mientras la base de datos está en un estado incoherente, entonces queda una base de datos dañada. Citando una página del sitio sqlite :

Si se produce un locking o pérdida de alimentación y queda un diario activo en el disco, es esencial que el archivo de base de datos original y el diario activo permanezcan en el disco con sus nombres originales hasta que otro proceso SQLite abra el archivo de base de datos y lo retrotraiga . […]

Sospechamos que un modo de falla común para la recuperación de SQLite ocurre así: se produce un corte de energía. Una vez que se restablece la energía, un usuario bien intencionado o un administrador del sistema comienza a buscar daño en el disco. Ven su archivo de base de datos llamado “important.data”. Este archivo es quizás familiar para ellos. Pero después de la caída, también hay un diario caliente llamado “important.data-journal”. El usuario luego elimina el diario dynamic, pensando que están ayudando a limpiar el sistema. No conocemos otra forma de evitar esto que la educación del usuario.

Se supone que la reversión se producirá automáticamente la próxima vez que se abra la base de datos, pero fallará si el proceso no puede bloquear la base de datos. Como otros han dicho, una posible razón para esto es que otro proceso actualmente lo tiene abierto. Otra posibilidad es un locking de NFS obsoleto, si la base de datos está en un volumen NFS. En ese caso, una solución alternativa es reemplazar el archivo de base de datos con una copia nueva que no esté bloqueada en el servidor NFS (mv database.db original.db; cp original.db database.db). Tenga en cuenta que las preguntas frecuentes de sqlite recomiendan precaución con respecto al acceso concurrente a las bases de datos en volúmenes NFS, debido a las implementaciones erróneas de locking de archivos NFS.

No puedo explicar por qué borrar un archivo de publicación le permitiría bloquear una base de datos que antes no podía. ¿Eso es reproducible?

Por cierto, la presencia de un archivo -journal no significa necesariamente que hubo un locking o que hay cambios que deben revertirse. Sqlite tiene algunos modos de diario diferentes, y en los modos PERSIST o TRUNCATE deja siempre el archivo -journal en su lugar, y cambia el contenido para indicar si hay transacciones parciales o no para revertir.

Si un proceso tiene un locking en una base de datos SQLite y se bloquea, el DB permanece bloqueado permanentemente. Ese es el problema. No es que algún otro proceso tenga un locking.

Si desea eliminar un error de “la base de datos está bloqueada”, siga estos pasos:

  1. Copie su archivo de base de datos a otra ubicación.
  2. Reemplace la base de datos con la base de datos copiada. Esto desreferenciará todos los procesos que estaban accediendo a su archivo de base de datos.

los archivos db SQLite son solo archivos, por lo que el primer paso sería asegurarse de que no sea de solo lectura. La otra cosa que debe hacer es asegurarse de que no tiene algún tipo de visor de DBI SQLite DB con el DB abierto. Puede tener el DB abierto en otro shell, o su código puede tener el DB abierto. Normalmente, esto se vería si un subproceso diferente o una aplicación como el Buscador de base de datos SQLite tiene el DB abierto para la escritura.

Tuve este problema ahora, usando una base de datos SQLite en un servidor remoto, almacenada en un assembly NFS. SQLite no pudo obtener un locking después de que la sesión de shell remoto que usé se bloqueó mientras la base de datos estaba abierta.

Las recetas de recuperación sugeridas anteriormente no me funcionaron (incluida la idea de mover primero y luego copiar la base de datos). Pero después de copiarlo a un sistema que no es NFS, la base de datos se volvió utilizable y no parece que se hayan perdido datos.

Encontré la documentación de los diversos estados de locking en SQLite para ser muy útil. Michael, si puede realizar lecturas pero no puede realizar escrituras en la base de datos, eso significa que un proceso ha obtenido un locking RESERVADO en su base de datos, pero aún no ha ejecutado la escritura. Si está usando SQLite3, hay un nuevo locking llamado PENDING donde no se permite la conexión de más procesos, pero las conexiones existentes pueden llevar a cabo lecturas, por lo que si este es el problema, debería verlo en su lugar.

Este error puede producirse si el archivo está en una carpeta remota, como una carpeta compartida. Cambié la base de datos a un directorio local y funcionó perfectamente.

Mi locking fue causado por el locking del sistema y no por un proceso de suspensión. Para resolver esto simplemente cambié el nombre del archivo y luego lo copié de nuevo a su nombre y ubicación originales.

Usando un shell de Linux que sería …

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

Tengo tal problema dentro de la aplicación, que tiene acceso a SQLite desde 2 conexiones, una era de solo lectura y la segunda para escribir y leer. Parece que la conexión de solo lectura bloqueó la escritura desde la segunda conexión. Finalmente, resulta que es necesario finalizar o, al menos, restablecer las declaraciones preparadas INMEDIATAMENTE después del uso. Hasta que se abra la statement preparada, causó que la base de datos se bloqueara para la escritura.

NO OLVIDE LLAMAR:

 sqlite_reset(xxx); 

o

 sqlite_finalize(xxx); 

Algunas funciones, como INDEX, pueden llevar mucho tiempo y bloquean toda la base de datos mientras se ejecuta. En instancias como esa, ¡podría incluso no usar el archivo de diario!

Entonces la mejor / única forma de verificar si su base de datos está bloqueada porque un proceso está ACTIVAMENTE escribiéndole (y por lo tanto debe dejarlo solo hasta que complete su operación) es md5 (o md5sum en algunos sistemas) el archivo dos veces . Si obtienes una sum de comprobación diferente, la base de datos se escribe, y realmente REALMENTE no quieres matar -9 ese proceso porque puedes terminar fácilmente con una tabla / base de datos corrupta si lo haces.

Voy a reiterar, porque es importante, la solución NO es encontrar el progtwig de locking y matarlo, sino encontrar si la base de datos tiene un locking de escritura por una buena razón, e ir desde allí. A veces la solución correcta es solo un descanso para tomar café.

La única forma de crear esta situación bloqueada pero no escrita es si su progtwig ejecuta BEGIN EXCLUSIVE , porque quería hacer algunas alteraciones en la tabla o algo, luego, por la razón que sea, nunca envía un END luego, y el proceso nunca termina . Las tres condiciones que se cumplen son muy poco probables en cualquier código escrito correctamente, y como tal, 99 veces de cada 100 cuando alguien quiere matar su proceso de locking, el proceso de locking realmente está bloqueando su base de datos por una buena razón. Los progtwigdores normalmente no agregan la condición BEGIN EXCLUSIVE menos que realmente lo necesiten, ya que previene la concurrencia y aumenta las quejas de los usuarios. SQLite solo lo agrega cuando realmente lo necesita (como al indexar).

Finalmente, el estado ‘bloqueado’ no existe DENTRO del archivo como varias respuestas han indicado – reside en el kernel del sistema operativo. El proceso que ejecutó BEGIN EXCLUSIVE ha solicitado al sistema operativo que se coloque un locking en el archivo. Incluso si su proceso exclusivo se ha bloqueado, su sistema operativo podrá determinar si debe mantener el locking de archivos o no. ¡No es posible terminar con una base de datos que está bloqueada, pero ningún proceso la está bloqueando activamente! Cuando se trata de ver qué proceso bloquea el archivo, generalmente es mejor usar lsof en lugar de fuser (esta es una buena demostración de por qué: https://unix.stackexchange.com/questions/94316/fuser-vs-lsof- to-check-files-en-use ). Alternativamente, si tiene DTrace (OSX), puede usar iosnoop en el archivo.

Pooling=truePooling=true ” a la cadena de conexión y funcionó.

Simplemente me sucedió algo similar: mi aplicación web pudo leer desde la base de datos, pero no pudo realizar inserciones o actualizaciones. Un reinicio de Apache resolvió el problema al menos temporalmente.

Sin embargo, sería bueno poder rastrear la causa raíz.

El comando lsof en mi entorno Linux me ayudó a descubrir que había un proceso pendiente que mantenía el archivo abierto.
Mató el proceso y el problema fue resuelto.

Este enlace resuelve el problema. : Cuando Sqlite da: Error bloqueado de la base de datos. Resolvió que mi problema puede ser útil para usted.

Y puede usar comenzar transacción y finalizar transacción para no hacer que la base de datos se bloquee en el futuro.

Debería ser un problema interno de la base de datos …
Para mí, se ha manifestado después de intentar navegar en la base de datos con “SQLite manager” …
Entonces, si no puede encontrar otro proceso, conéctese a la base de datos y simplemente no puede arreglarlo, simplemente intente con esta solución radical:

  1. Proporcione exportar sus tablas (Puede usar “SQLite manager” en Firefox)
  2. Si la migración altera su esquema de base de datos, elimine la última migración fallida
  3. Cambie el nombre de su archivo “database.sqlite”
  4. Ejecute “rake db: migrate” para crear una nueva base de datos funcional
  5. Proporcione los permisos correctos a la base de datos para la importación de tablas
  6. Importe sus tablas respaldadas
  7. Escribe la nueva migración
  8. Ejecútelo con ” rake db:migrate

Me encontré con este mismo problema en Mac OS X 10.5.7 ejecutando scripts de Python desde una sesión de terminal. A pesar de que había detenido las secuencias de comandos y que la ventana del terminal estaba en el indicador de comandos, generaría este error la próxima vez que se ejecutara. La solución fue cerrar la ventana del terminal y luego abrirla nuevamente. No tiene sentido para mí, pero funcionó.

Acabo de tener el mismo error. Después de 5 mints google-ing encontré que no cerré a un shell witch que usaba el DB. Solo cierra y vuelve a intentarlo;)

Yo tuve el mismo problema. Aparentemente, la función de deshacer parece sobrescribir el archivo db con el diario, que es el mismo que el archivo db pero sin el cambio más reciente. Lo he implementado en mi código a continuación y ha estado funcionando bien desde entonces, mientras que antes mi código se quedaba atascado en el ciclo ya que la base de datos permanecía bloqueada.

Espero que esto ayude

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

Una razón común para obtener esta excepción es cuando intenta realizar una operación de escritura mientras aún tiene recursos para una operación de lectura. Por ejemplo, si SELECCIONA en una tabla, y luego intenta ACTUALIZAR algo que ha seleccionado sin cerrar su ResultSet primero.

Antes de bajar la opción de reinicio, vale la pena ver si puede encontrar el usuario de la base de datos sqlite.

En Linux, uno puede emplear fuser para este fin:

 $ fuser database.db $ fuser database.db-journal 

En mi caso, recibí la siguiente respuesta:

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

Lo que demostró que tenía otro progtwig de Python con pid 3556 (manage.py) usando la base de datos.

Una vieja pregunta, con muchas respuestas, estos son los pasos que he seguido recientemente al leer las respuestas anteriores, pero en mi caso el problema se debió al intercambio de recursos cifs. Este caso no se informó anteriormente, así que espero que ayude a alguien.

  • Compruebe que no haya conexiones abiertas en su código java.
  • Compruebe que no haya otros procesos utilizando su archivo SQLite db con lsof.
  • Compruebe que el propietario del usuario de su proceso de ejecución de jvm tiene permisos de r / w sobre el archivo.
  • Intente forzar el modo de locking en la apertura de la conexión con

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

Si está utilizando su archivo db SQLite sobre una carpeta compartida NFS, verifique este punto del FAQ de SQLite y revise sus opciones de configuración de assembly para asegurarse de que no se bloquee, como se describe aquí :

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

Obtuve este error en un escenario un poco diferente de los que se describen aquí.

La base de datos SQLite descansaba en un sistema de archivos NFS compartido por 3 servidores. En 2 de los servidores pude ejecutar consultas en la base de datos con éxito, en el tercero pensé que estaba recibiendo el mensaje “la base de datos está bloqueada”.

La cosa con esta 3ra máquina era que no le quedaba espacio en /var . Cada vez que traté de ejecutar una consulta en CUALQUIER base de datos SQLite ubicada en este sistema de archivos, recibí el mensaje “La base de datos está bloqueada” y también este error sobre los registros:

8 de agosto 10:33:38 server01 kernel: lockd: no se puede controlar 172.22.84.87

Y este también:

08 de agosto 10:33:38 server01 rpc.statd [7430]: No se pudo insertar: escribir /var/lib/nfs/statd/sm/other.server.name.com: no queda espacio en el dispositivo 8 de agosto 10:33: 38 server01 rpc.statd [7430]: STAT_FAIL al servidor01 para SM_MON de 172.22.84.87

Después de manejar la situación espacial, todo volvió a la normalidad.

De tus comentarios anteriores dijiste que había un archivo -journal presente.

Esto podría significar que ha abierto una transacción (¿EXCLUSIVO?) Y aún no ha confirmado los datos. ¿Tu progtwig o algún otro proceso salió del -journal?

Al reiniciar el proceso de sqlite, se examinará el archivo de diario y se eliminarán las acciones no confirmadas y se eliminará el archivo -journal.

Como ha dicho Seun Osewa, a veces un proceso zombie se ubicará en la terminal con un locking adquirido, incluso si no lo crees posible. Su secuencia de comandos se ejecuta, se bloquea y vuelve al aviso, pero hay un proceso zombie generado en alguna parte por una llamada a la biblioteca, y ese proceso tiene el locking.

Cerrar el terminal en el que estaba (en OSX) podría funcionar. El reinicio funcionará. Podría buscar procesos “python” (por ejemplo) que no están haciendo nada y matarlos.

puede intentar esto: .timeout 100 para establecer el tiempo de espera. No sé lo que sucede en la línea de comandos, pero en C # .Net cuando hago esto: "UPDATE table-name SET column-name = value;" Me sale La base de datos está bloqueada, pero este "UPDATE table-name SET column-name = value" va bien.

Parece que al agregar;, sqlite buscará más comandos.

Obtuve este error al usar Delphi con los componentes de LiteDAC. Resultó que solo ocurrió mientras ejecutaba mi aplicación desde Delphi IDE si la propiedad Connected se estableció en True para el componente de conexión SQLite (en este caso TLiteConnection).

Adminer es una pequeña (pero poderosa) alternativa de phpmyadmin que uso para monitorear la base de datos sqlite. Por algún motivo, la base de datos se bloqueó. Así es como lo arreglé.

  1. Descargué el archivo sqlite a mi sistema (FTP)
  2. Eliminado el archivo sqlite en línea
  3. Subido el archivo nuevamente al proveedor de hosting

Funciona bien ahora.