sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Как разблокировать базу данных, чтобы это работало?
sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Как разблокировать базу данных, чтобы это работало?
Ответы:
В Windows вы можете попробовать эту программу http://www.nirsoft.net/utils/opened_files_view.html, чтобы узнать, как процесс обрабатывает файл БД. Попробуйте закрыть эту программу для разблокировки базы данных
В Linux и macOS вы можете сделать что-то подобное, например, если ваш заблокированный файл - development.db:
$ fuser development.db
Эта команда покажет, какой процесс блокирует файл:
> development.db: 5430
Просто убей процесс ...
убить -9 5430
... И ваша база данных будет разблокирована.
kill
будет хорошо, но вы должны быть осторожны, чтобы убить его должным образом, и kill -9
, вероятно, это неправильно и / или излишне. Если процесс завис и не умрет иначе, иногда вам это нужно kill -9
. Но вы не хотите идти и убивать основное производственное задание, просто чтобы сообщить, что база данных больше не заблокирована!
Я вызвал блокировку базы данных sqlite из-за сбоя приложения во время записи. Вот как я это исправил:
echo ".dump" | sqlite old.db | sqlite new.db
Взято из: 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)
Страница DatabaseIsLocked, указанная ниже, больше не доступна. Страница Блокировка и параллелизм файлов описывает изменения, связанные с блокировкой файлов, представленные в версии 3, и может быть полезна для будущих читателей. https://www.sqlite.org/lockingv3.html
Страница SQLite wiki DatabaseIsLocked предлагает хорошее объяснение этого сообщения об ошибке. Отчасти утверждается, что источник разногласий является внутренним (для процесса, выдающего ошибку).
Эта страница не объясняет, как SQLite решает, что что-то в вашем процессе имеет блокировку, и какие условия могут привести к ложному срабатыванию.
Удаление файла -journal звучит как ужасная идея. Он позволяет sqlite откатывать базу данных до согласованного состояния после сбоя. Если вы удалите его, когда база данных находится в несогласованном состоянии, то у вас останется поврежденная база данных. Ссылаясь на страницу с сайта sqlite :
Если происходит сбой или сбой питания, и на диске остается горячий журнал, важно, чтобы исходный файл базы данных и горячий журнал оставались на диске с их исходными именами, пока файл базы данных не будет открыт другим процессом SQLite и откатан , [...]
Мы подозреваем, что обычный режим сбоя для восстановления SQLite происходит следующим образом: происходит сбой питания. После восстановления питания доброжелательный пользователь или системный администратор начинает осматривать диск на предмет повреждений. Они видят файл своей базы данных с именем "Important.data". Возможно, этот файл им знаком. Но после сбоя есть еще и горячий журнал под названием «важное.данные-журнал». Затем пользователь удаляет горячий журнал, думая, что он помогает очистить систему. Мы не знаем никакого способа предотвратить это, кроме обучения пользователей.
Предполагается, что откат произойдет автоматически при следующем открытии базы данных, но произойдет сбой, если процесс не сможет заблокировать базу данных. Как уже говорили другие, одна из возможных причин этого заключается в том, что в настоящее время этот процесс открыт. Другая возможность - устаревшая блокировка NFS, если база данных находится на томе NFS. В этом случае обходным путем является замена файла базы данных новой копией, которая не заблокирована на сервере NFS (mv database.db original.db; cp original.db database.db). Обратите внимание, что в FAQ по sqlite рекомендуется соблюдать осторожность при одновременном доступе к базам данных на томах NFS из-за ошибочных реализаций блокировки файлов NFS.
Я не могу объяснить, почему удаление файла -journal позволило бы вам заблокировать базу данных, которую вы не могли раньше. Это воспроизводимо?
Кстати, наличие файла -journal не обязательно означает, что произошел сбой или есть изменения, которые необходимо откатить. Sqlite имеет несколько разных режимов ведения журнала, а в режимах PERSIST или TRUNCATE он всегда оставляет файл -journal на своем месте и изменяет его содержимое, чтобы указать, существуют ли частичные транзакции для отката.
Если вы хотите удалить ошибку «база данных заблокирована», выполните следующие действия:
Если у процесса есть блокировка на базе данных SQLite и происходит сбой, она остается заблокированной навсегда. Это проблема. Дело не в том, что какой-то другой процесс имеет блокировку.
файлы базы данных SQLite - это просто файлы, поэтому первым шагом было бы убедиться, что они не только для чтения. Другая вещь, которую нужно сделать, - убедиться, что у вас нет какой-либо программы просмотра БД SQLite с графическим интерфейсом при открытой БД. Вы можете открыть базу данных в другой оболочке, или ваш код может открыть базу данных. Обычно это можно увидеть, если в другом потоке или приложении, таком как SQLite Database Browser, БД открыта для записи.
У меня была эта проблема только сейчас, с использованием базы данных SQLite на удаленном сервере, хранящейся в монтировании NFS. SQLite не удалось получить блокировку после того, как сеанс удаленной оболочки, который я использовал, потерпел крах, когда база данных была открыта.
Предложенные выше рецепты восстановления не сработали (включая идею сначала переместить, а затем скопировать базу данных обратно). Но после копирования в систему, отличную от NFS, база данных стала пригодной для использования, и данные, похоже, не были потеряны.
Моя блокировка была вызвана сбоем системы, а не зависанием. Чтобы решить эту проблему, я просто переименовал файл, а затем скопировал его обратно в исходное имя и местоположение.
Использование оболочки Linux, которая была бы ...
mv mydata.db temp.db
cp temp.db mydata.db
Я добавил " Pooling=true
" в строку подключения, и это сработало.
Я нашел документацию о различных состояниях блокировки в SQLite очень полезной. Майкл, если вы можете выполнять чтение, но не можете выполнять запись в базу данных, это означает, что процесс получил зарезервированную блокировку в вашей базе данных, но еще не выполнил запись. Если вы используете SQLite3, есть новая блокировка, называемая PENDING, в которой больше не разрешено подключать больше процессов, но существующие соединения могут выполнять чтение, поэтому, если это проблема, вы должны рассмотреть ее.
У меня есть такая проблема в приложении, что доступ к SQLite из 2-х подключений - одно только для чтения, а второе для записи и чтения. Похоже, что соединение только для чтения заблокировало запись со второго соединения. Наконец, оказывается, что необходимо завершить или, по крайней мере, сбросить подготовленные операторы НЕМЕДЛЕННО после использования. До тех пор, пока готовый оператор не будет открыт, он вызвал, что база данных была заблокирована для записи.
НЕ ЗАБЫВАЙТЕ ЗВОНИТЬ:
sqlite_reset(xxx);
или
sqlite_finalize(xxx);
Некоторые функции, такие как INDEX'ing, могут занимать очень много времени и блокировать всю базу данных во время работы. В таких случаях он может даже не использовать файл журнала!
Поэтому лучший / единственный способ проверить, заблокирована ли ваша база данных, потому что процесс АКТИВНО записывает в нее (и, таким образом, вы должны оставить его в покое, пока он не завершит свою работу), - это md5 (или md5sum в некоторых системах) файл дважды , Если вы получаете другую контрольную сумму, база данных пишется, и вы действительно ДЕЙСТВИТЕЛЬНО не хотите уничтожать этот процесс, потому что вы можете легко получить поврежденную таблицу / базу данных, если вы это сделаете.
Я еще раз повторю, потому что это важно - решение НЕ в том, чтобы найти программу блокировки и убить ее, а в том, чтобы найти, есть ли в базе данных блокировка записи по уважительной причине, и пойти дальше. Иногда правильное решение - просто перерыв на кофе.
Единственный способ создать эту заблокированную, но не записываемую ситуацию - это если ваша программа выполняется BEGIN EXCLUSIVE
, потому что она хотела внести какие-то изменения в таблицу или что-то еще, то по какой-либо причине никогда не отправляет END
потом, и процесс никогда не завершается . Все три выполняемых условия крайне маловероятны в любом правильно написанном коде, и, таким образом, в 99 случаях из 100, когда кто-то хочет уничтожить -9 свой процесс блокировки, процесс блокировки фактически блокирует вашу базу данных по уважительной причине. Программисты обычно не добавляютBEGIN EXCLUSIVE
условие, если в этом нет особой необходимости, поскольку оно предотвращает параллелизм и увеличивает количество жалоб пользователей. Сам SQLite добавляет его только тогда, когда это действительно необходимо (например, при индексации).
Наконец, статус «заблокирован» не существует ВНУТРИ файла, как указано в нескольких ответах, - он находится в ядре операционной системы. Запущенный процесс BEGIN EXCLUSIVE
запросил у ОС блокировку файла. Даже если ваш эксклюзивный процесс потерпел крах, ваша ОС сможет выяснить, должна ли она поддерживать блокировку файла или нет !! Невозможно получить базу данных, которая заблокирована, но ни один процесс не блокирует ее активно !! Когда дело доходит до выяснения, какой процесс блокирует файл, обычно лучше использовать lsof, а не fuser (это хорошая демонстрация того, почему: /unix/94316/fuser-vs-lsof- проверять используемые файлы ). Кроме того, если у вас есть DTrace (OSX), вы можете использовать iosnoop для файла.
У меня только что произошло нечто подобное - мое веб-приложение могло читать из базы данных, но не могло выполнять вставки или обновления. Перезагрузка Apache решила проблему хотя бы временно.
Было бы хорошо, однако, иметь возможность отследить основную причину.
Эта ссылка решит проблему. : Когда Sqlite дает: Ошибка блокировки базы данных Это решило мою проблему, может быть полезно для вас.
И вы можете использовать начало транзакции и конец транзакции, чтобы не блокировать базу данных в будущем.
Должна быть внутренняя проблема базы данных ...
Для меня это проявилось после попытки просмотреть базу данных с помощью "менеджера SQLite" ...
Итак, если вы не можете найти другой процесс, подключающийся к базе данных, и просто не можете это исправить, просто попробуйте это радикальное решение:
rake db:migrate
"Я столкнулся с этой же проблемой на Mac OS X 10.5.7, где выполнялись скрипты 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 )
Одна из распространенных причин получения этого исключения - это когда вы пытаетесь выполнить операцию записи, в то же время удерживая ресурсы для операции чтения. Например, если вы ВЫБИРАЕТЕ из таблицы, а затем пытаетесь ОБНОВИТЬ что-то, что вы выбрали, не закрывая сначала свой ResultSet.
У меня также были ошибки «база данных заблокирована» в многопоточном приложении, которое выглядит как код результата SQLITE_BUSY , и я решил эту проблему, установив для sqlite3_busy_timeout что-то подходящее длинное, например 30000.
(Кстати, как странно, что по 7-летнему вопросу никто не узнал об этом уже! SQLite действительно необычный и удивительный проект ...)
Прежде чем перейти к параметру перезагрузки, стоит посмотреть, сможете ли вы найти пользователя базы данных sqlite.
В Linux можно использовать fuser
для этой цели:
$ fuser database.db
$ fuser database.db-journal
В моем случае я получил следующий ответ:
philip 3556 4700 0 10:24 pts/3 00:00:01 /usr/bin/python manage.py shell
Это показало, что у меня была другая программа на Python с pid 3556 (manage.py), использующая базу данных.
Старый вопрос с множеством ответов, вот шаги, которые я недавно выполнил, прочитав ответы выше, но в моем случае проблема была из-за совместного использования ресурсов cifs. Об этом случае не сообщалось ранее, поэтому надеюсь, что это кому-нибудь поможет.
Попробуйте включить режим блокировки на открытии соединения с
final SQLiteConfig config = new SQLiteConfig();
config.setReadOnly(false);
config.setLockingMode(LockingMode.NORMAL);
connection = DriverManager.getConnection(url, config.toProperties());
Если вы используете файл базы данных SQLite в общей папке NFS, проверьте этот пункт часто задаваемых вопросов о SQLite и просмотрите параметры конфигурации подключения, чтобы убедиться, что вы избегаете блокировок, как описано здесь :
//myserver /mymount cifs username=*****,password=*****,iocharset=utf8,sec=ntlm,file,nolock,file_mode=0700,dir_mode=0700,uid=0500,gid=0500 0 0
Я получил эту ошибку в сценарии, немного отличающемся от описанного здесь.
База данных SQLite покоилась в файловой системе NFS, используемой тремя серверами. На двух серверах я смог успешно выполнить запросы к базе данных, на третьем мне показалось, что я получаю сообщение «база данных заблокирована».
Дело в том, что с этой 3-ей машиной не осталось места /var
. Каждый раз, когда я пытался выполнить запрос в ЛЮБОЙ базе данных SQLite, расположенной в этой файловой системе, я получал сообщение «база данных заблокирована», а также эта ошибка в журналах:
8 августа 10:33:38 server01 kernel: lockd: не может контролировать 172.22.84.87
И этот тоже:
8 августа 10:33:38 server01 rpc.statd [7430]: Не удалось вставить: writing /var/lib/nfs/statd/sm/other.server.name.com: на устройстве не осталось места 8 августа 10:33: 38 server01 rpc.statd [7430]: STAT_FAIL для server01 для SM_MON из 172.22.84.87
После того, как космическая ситуация была обработана, все пришло в норму.
Если вы пытаетесь разблокировать базу данных Chrome, чтобы просмотреть ее с помощью SQLite , просто выключите Chrome.
Windows
%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
макинтош
~/Library/Application Support/Google/Chrome/Default/Web Data
Из ваших предыдущих комментариев вы сказали, что файл -journal присутствовал.
Это может означать, что вы открыли и (ИСКЛЮЧИТЕЛЬНО?) Транзакцию и еще не зафиксировали данные. Ваша программа или какой-то другой процесс оставили журнал?
Перезапуская процесс sqlite, вы увидите файл журнала, очистите все незафиксированные действия и удалите файл -journal.
Как сказал Сеун Осева, иногда процесс зомби будет сидеть в терминале с заблокированным замком, даже если вы не думаете, что это возможно. Ваш сценарий запускается, аварийно завершает работу, и вы возвращаетесь к приглашению, но где-то в процессе вызова библиотеки появляется процесс зомби, и этот процесс заблокирован.
Закрытие терминала, в котором вы были (в OSX), может работать. Перезагрузка будет работать. Например, вы можете искать процессы «python», которые ничего не делают, и убивать их.
Вы можете попробовать это: .timeout 100
установить время ожидания. Я не знаю, что происходит в командной строке, но в C # .Net, когда я делаю это: "UPDATE table-name SET column-name = value;"
я получаю База данных заблокирована, но это"UPDATE table-name SET column-name = value"
все идет хорошо.
Похоже, при добавлении; sqlite будет искать дальнейшие команды.