sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
¿Cómo desbloqueo la base de datos para que esto funcione?
sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
¿Cómo desbloqueo la base de datos para que esto funcione?
Respuestas:
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. Intenta 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
Solo mata el proceso ...
matar -9 5430
... Y tu base de datos se desbloqueará.
kill
debería estar bien, pero debe tener cuidado de matarlo correctamente, y kill -9
probablemente sea incorrecto o excesivo. Si el proceso se cuelga y de lo contrario no morirá, a veces es necesario kill -9
. ¡Pero no quiere ir y matar el trabajo de producción principal solo para poder informar que la base de datos ya no está bloqueada!
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
sqlite> .dump PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; /**** ERROR: (5) database is locked *****/ ROLLBACK; -- due to errors
FOREIGN KEY constraint failed (RELEASE RESTOREPOINT)
La página DatabaseIsLocked que se enumera 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
La página SQLite wiki 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 tiene 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 dinámico permanezcan en el disco con sus nombres originales hasta que otro proceso SQLite abra el archivo de la base de datos y lo revierta . [...]
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 energía, 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 del bloqueo de archivos NFS.
No puedo explicar por qué eliminar un archivo -journal 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 siempre el archivo de diario en su lugar y cambia el contenido para indicar si hay o no transacciones parciales para revertir.
Si desea eliminar el error "la base de datos está bloqueada", siga estos pasos:
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 SQLite db 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 GUI SQLite DB con el DB abierto. 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.
Tuve este problema hace un momento, 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 el bloqueo 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ó.
Encontré que la documentación de los diversos estados de bloqueo en SQLite es 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 permiten más procesos para conectarse, pero las conexiones existentes pueden realizar lecturas, por lo que si este es el problema, debería considerarlo.
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 se requiere 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, 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 continuar desde allí. A veces la solución correcta es solo un descanso para tomar café.
La única forma de crear esta situación de bloqueo pero no estar escrito es si su programa se ejecuta BEGIN EXCLUSIVE
, porque quería hacer algunas alteraciones en la tabla o algo así, por cualquier motivo nunca envía un mensaje END
posterior 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 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 generalmente no agregan la BEGIN EXCLUSIVE
condición 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 se 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é: /unix/94316/fuser-vs-lsof- para verificar archivos en uso ). 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.
Sin embargo, sería bueno 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 serle útil.
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 el "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:
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, daría este error la próxima vez que se ejecute. La solución fue cerrar la ventana del terminal y luego volver a abrirla. No tiene sentido para mí, pero funcionó.
Yo 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
##############
#### 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 intenta ACTUALIZAR algo que ha seleccionado sin cerrar su ResultSet primero.
También tenía errores de "la base de datos está bloqueada" en una aplicación multiproceso, que parece ser el código de resultado SQLITE_BUSY , y lo resolví estableciendo 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 ...)
Antes de pasar a la opción de reinicio, vale la pena ver si puede encontrar el usuario de la base de datos sqlite.
En Linux, se puede emplear fuser
para este fin:
$ fuser database.db
$ fuser database.db-journal
En mi caso obtuve 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 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.
Intente 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, verifique este punto de las preguntas frecuentes de SQLite y revise las 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
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 recibía el mensaje "la base de datos está bloqueada".
Lo que sucedió con esta tercera máquina fue que no le quedaba espacio /var
. Cada vez que intenté 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 en 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.
Si está intentando desbloquear la base de datos de Chrome para verla con SQLite , simplemente cierre Chrome.
Ventanas
%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
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?
Reiniciar el proceso sqlite mirará el archivo de diario y limpiará cualquier acción no confirmada y eliminará el archivo de diario.
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 estabas (en OSX) podría funcionar. Reiniciar funcionará. Puede buscar procesos "python" (por ejemplo) que no estén haciendo nada y matarlos.
puedes probar esto: .timeout 100
para establecer 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 que la base de datos está bloqueada, pero esto "UPDATE table-name SET column-name = value"
funciona bien.
Parece que cuando agrega;, sqlite buscará más comandos.