Pregunta

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

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

¿Fue útil?

Solución

En Windows puede probar este programa http://www.nirsoft.net/utils/opened_files_view .html para descubrir que el proceso está manejando el archivo db. Intente cerrar ese programa 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

Simplemente elimine el proceso ...

  

kill -9 5430

... Y su base de datos se desbloqueará.

Otros consejos

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- una base de datos sqlite

La página DatabaseIsLocked que figura a continuación ya no está disponible. La página de bloqueo y concurrencia de archivos describe los cambios relacionados con el bloqueo de archivos introducidos en v3 y pueden ser útiles para futuros lectores. https://www.sqlite.org/lockingv3.html

El wikiite SQLite La página DatabaseIsLocked 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 bloqueo y qué condiciones podrían conducir a un falso positivo.

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

  

Si se produce un bloqueo o una pérdida de energía y se deja 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 archivo SQLite abra el archivo de la base de datos. y retrocedió [...]

     

Sospechamos que un modo de falla común para la recuperación de SQLite ocurre así: se produce una falla de energía. Una vez que se restablece la alimentación, un usuario o administrador del sistema bien intencionado comienza a buscar daños en el disco. Ven su archivo de base de datos llamado " important.data " ;. Este archivo quizás les sea familiar. Pero después del accidente, también hay un diario caliente llamado "important.data-journal". Luego, el usuario elimina el diario activo, pensando que está ayudando a limpiar el sistema. No conocemos otra forma de prevenir esto que no sea la educación del usuario.

Se supone que la reversión sucederá 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 han dicho otros, una posible razón para esto es que otro proceso actualmente lo tiene abierto. Otra posibilidad es un bloqueo NFS obsoleto, si la base de datos está en un volumen NFS. En ese caso, una solución alternativa es reemplazar el archivo de la 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 bases de datos en volúmenes NFS, debido a implementaciones defectuosas de bloqueo de archivos NFS.

No puedo explicar por qué eliminar un archivo de diario le permitiría bloquear una base de datos que antes no podía. ¿Es eso reproducible?

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

Si desea eliminar una " la base de datos está bloqueada " error luego 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.

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

los archivos db de 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 GUI SQLite DB con la base de datos abierta. Puede tener la base de datos abierta en otro shell, o su código puede tener la base de datos abierta. Por lo general, vería esto si un subproceso diferente o una aplicación como el Navegador de base de datos SQLite tiene la base de datos abierta para escribir.

Hace poco tuve este problema, usando una base de datos SQLite en un servidor remoto, almacenado en un soporte NFS. SQLite no pudo obtener un bloqueo después de que la sesión de shell remota que utilicé se bloqueó mientras la base de datos estaba abierta.

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

Mi bloqueo fue causado por la falla del sistema y no por un proceso de bloqueo. Para resolver esto, simplemente cambié el nombre del archivo y luego lo volví a copiar 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

Agregué " Pooling = true " a la cadena de conexión y funcionó.

La documentación de los diversos estados de bloqueo en SQLite me pareció muy útil. Michael, si puedes realizar lecturas pero no puedes realizar escrituras en la base de datos, eso significa que un proceso ha obtenido un bloqueo RESERVADO en tu base de datos pero aún no ha ejecutado la escritura. Si está utilizando SQLite3, hay un nuevo bloqueo llamado PENDIENTE en el que no se permite que se conecten más procesos, pero las conexiones existentes pueden realizar lecturas, por lo que si este es el problema, debería considerarlo.

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

Tengo ese problema dentro de la aplicación, que accede a SQLite desde 2 conexiones: una era de solo lectura y la segunda para escribir y leer. Parece que esa 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 declaración preparada, la base de datos se bloqueó para escritura.

NO OLVIDES LA LLAMADA:

sqlite_reset(xxx);

o

sqlite_finalize(xxx);

Algunas funciones, como INDEX'ing, pueden tomar mucho tiempo, y bloquea toda la base de datos mientras se ejecuta. En casos como ese, ¡es posible que ni siquiera use el archivo de diario!

Entonces, la mejor / única forma de verificar si su base de datos está bloqueada porque un proceso le está escribiendo ACTIVAMENTE (y, por lo tanto, debe dejarla en paz hasta que se complete su operación) es md5 (o md5sum en algunos sistemas) el archivo dos veces Si obtiene una suma de comprobación diferente, la base de datos se está escribiendo, y realmente REALMENTE no desea eliminar -9 ese proceso porque puede terminar fácilmente con una tabla / base de datos corrupta si lo hace.

Reitero, porque es importante, la solución NO es encontrar el programa de bloqueo y matarlo, es encontrar si la base de datos tiene un bloqueo de escritura por una buena razón, y seguir 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 programa ejecuta BEGIN EXCLUSIVE , porque quería hacer algunas alteraciones en la tabla o algo así, para lo que sea Motivo nunca envía un END después, y el proceso nunca termina . Las tres condiciones que se cumplen son altamente improbables en cualquier código escrito correctamente, y como tal 99 de cada 100 veces cuando alguien quiere matar -9 su proceso de bloqueo, el proceso de bloqueo en realidad está bloqueando su base de datos por una buena razón. Los programadores no suelen agregar la condición BEGIN EXCLUSIVE a menos que realmente lo necesiten, porque evita la concurrencia y aumenta las quejas de los usuarios. SQLite solo lo agrega cuando realmente lo necesita (como cuando se indexa).

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

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

Sería bueno, sin embargo, poder rastrear la causa raíz.

El comando

lsof en mi entorno Linux me ayudó a descubrir que se estaba bloqueando un proceso manteniendo abierto el archivo.
Mató el proceso y se resolvió el problema.

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

Y puede usar comenzar transacción y finalizar transacción para no bloquear la base de datos en el futuro.

Debería ser el problema interno de una base de datos ...
Para mí, se ha manifestado después de intentar explorar la base de datos con " Administrador de SQLite " ...
Entonces, si no puede encontrar otro proceso, conéctese a la base de datos y simplemente no puede solucionarlo, solo prueba esta solución radical:

  1. Proporcione para 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 " database.sqlite " archivo
  4. Ejecutar " rake db: migrate " hacer una nueva base de datos de trabajo
  5. Proporcionar para otorgar los permisos correctos a la base de datos para la importación de tablas
  6. Importa tus tablas respaldadas
  7. Escribir 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. Aunque había detenido las secuencias de comandos y la ventana de terminal estaba en el símbolo del sistema, me daría este error la próxima vez que se ejecutara. La solución fue cerrar la ventana del terminal y luego volver a abrirla. No tiene sentido para mí, pero funcionó.

Acabo de tener el mismo error. Después de 5 minets google-ing descubrí que no había cerrado un shell que usaba el db. Simplemente ciérrelo e intente nuevamente;)

Tuve el mismo problema. Aparentemente, la función de reversión parece sobrescribir el archivo db con el diario, que es el mismo que el archivo db pero sin el cambio más reciente. He implementado esto en mi código a continuación y ha estado funcionando bien desde entonces, mientras que antes mi código simplemente se quedaba bloqueado mientras la base de datos permanecía bloqueada.

Espero que esto ayude

mi código de 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 mantiene recursos para una operación de lectura. Por ejemplo, si SELECCIONA de una tabla y luego trata de ACTUALIZAR algo que ha seleccionado sin cerrar su ResultSet primero.

Antes de pasar a la opción de reinicio, vale la pena ver si puede encontrar al 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 mostró que tenía otro programa de Python con pid 3556 (manage.py) usando la base de datos.

Una vieja pregunta, con muchas respuestas, aquí están los pasos que he seguido recientemente leyendo 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.

  • Verifique que no haya conexiones abiertas en su código Java.
  • Verifique que ningún otro proceso esté utilizando su archivo db SQLite con lsof.
  • Verifique que el propietario del usuario de su proceso jvm en ejecución tenga permisos r / w sobre el archivo.
  • Intenta forzar el modo de bloqueo 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 SQLite db sobre una carpeta compartida NFS, marque este punto de las preguntas frecuentes de SQLite, y revise sus opciones de configuración de montaje para asegurarse de evitar bloqueos, 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

Recibí 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 obteniendo la "base de datos bloqueada". mensaje.

Lo que sucedió con esta tercera máquina fue que no le quedaba espacio en / var . Cada vez que intentaba ejecutar una consulta en CUALQUIER base de datos SQLite ubicada en este sistema de archivos, obtenía la "base de datos bloqueada". mensaje y también este error sobre los registros:

  

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

Y este también:

  

8 de agosto 10:33:38 server01 rpc.statd [7430]: Error al insertar: escribiendo /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 de diario.

Esto podría significar que ha abierto una transacción (¿EXCLUSIVA?) y aún no ha confirmado los datos. ¿Su programa o algún otro proceso dejó atrás el diario?

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

Como dijo Seun Osewa, a veces un proceso zombie se sentará en la terminal con un bloqueo adquirido, incluso si no lo crees posible. Su secuencia de comandos se ejecuta, se bloquea y vuelve a la solicitud, pero hay un proceso zombie generado en algún lugar por una llamada a la biblioteca, y ese proceso tiene el bloqueo.

Cerrar el terminal en el que estaba (en OSX) podría funcionar. Reiniciar funcionará. Podrías buscar "python" procesos (por ejemplo) que no están haciendo nada y los matan.

puede intentar esto: .timeout 100 para configurar el tiempo de espera. No sé qué sucede en la línea de comandos, pero en C # .Net cuando hago esto: " UPDATE table-name SET column-name = value; " Obtengo La base de datos está bloqueada pero esto < code> " UPDATE table-name SET column-name = value " funciona bien.

Parece que cuando agrega;, sqlite buscará más comandos.

Recibí este error cuando uso Delphi con los componentes LiteDAC. Resultó que solo sucedió mientras ejecutaba mi aplicación desde el IDE de Delphi si la propiedad Connected se estableció en True para el componente de conexión SQLite (en este caso, TLiteConnection).

Estaba teniendo "la base de datos está bloqueada" errores en una aplicación multiproceso también, que parece ser el SQLITE_BUSY , y yo lo resolvió con la configuración sqlite3_busy_timeout en algo adecuadamente largo como 30000.

(En una nota al margen, ¡qué extraño que en una pregunta de 7 años ya nadie lo haya descubierto! SQLite realmente es un proyecto peculiar y sorprendente ...)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top