Вопросы | sqlite

Как разблокировать базу данных SQLite?

Вопрос

ryantm | 311980 просмотров | рейтинг: 0

 sqlite> DELETE FROM mails WHERE (id = 71);
SQL error: database is locked
 
Как разблокировать базу данных, чтобы это работало?

Комментарии:

unexist

У меня была та же проблема, проблема была в антивирусе, когда я деактивировал его, мое приложение работало хорошо, но когда я активировал его, я обнаружил, что какая-то база данных об ошибках заблокирована, я надеюсь, что это поможет вам.


user8510915

Может быть другой процесс обращается к файлу базы данных - вы проверяли lsof?




Ответы

Kyle Cronin

+ 10 -
файлы базы данных SQLite - это просто файлы, поэтому первым шагом было бы убедиться, что они не только для чтения. Другая вещь, которую нужно сделать, это убедиться, что у вас нет какой-либо программы просмотра БД SQLite с графическим интерфейсом при открытой БД. Вы можете открыть базу данных в другой оболочке, или ваш код может открыть базу данных. Обычно это можно увидеть, если в другом потоке или приложении, таком как SQLite Database Browser, БД открыта для записи.  


Heat Miser

+ 51 -
Вики-страница SQLite DatabaseIsLocked предлагает хорошее объяснение этого сообщения об ошибке. Отчасти утверждается, что источник разногласий является внутренним (процесс, выдавший ошибку). Эта страница не объясняет, как SQLite решает, что что-то в вашем процессе имеет блокировку, и какие условия могут привести к ложному срабатыванию.  


Ben L

+ 2 -
У меня только что произошло нечто подобное - мое веб-приложение могло читать из базы данных, но не могло выполнять вставки или обновления. Перезагрузка Apache решила проблему хотя бы временно. Было бы хорошо, однако, иметь возможность отследить первопричину.  


converter42

+ 4 -
Я нашел документацию о различных состояниях блокировки в SQLite очень полезной. Майкл, если вы можете выполнять чтение, но не можете выполнять запись в базу данных, это означает, что процесс получил зарезервированную блокировку в вашей базе данных, но еще не выполнил запись. Если вы используете SQLite3, есть новая блокировка PENDING, в которой больше не разрешено подключать больше процессов, но существующие соединения могут выполнять чтение, поэтому если вы столкнулись с этой проблемой, вам следует рассмотреть ее.  


Shawn Swaner

+ 0 -
Из ваших предыдущих комментариев вы сказали, что файл -journal присутствовал. Это может означать, что вы открыли и (ИСКЛЮЧИТЕЛЬНО?) Транзакцию и еще не зафиксировали данные. Ваша программа или какой-то другой процесс оставили журнал? Перезапуская процесс sqlite, вы увидите файл журнала, очистите все незафиксированные действия и удалите файл -journal.  


Stijn Sanders

+ 1 -
Я столкнулся с этой же проблемой на Mac OS X 10.5.7, где выполнялись скрипты Python из терминальной сессии. Несмотря на то, что я остановил сценарии, а окно терминала находилось в командной строке, при следующем запуске оно выдаст эту ошибку. Решением было закрыть окно терминала, а затем снова открыть его. Не имеет смысла для меня, но это сработало.  


TheSteven

+ 3 -
Моя блокировка была вызвана сбоем системы, а не зависанием. Чтобы решить эту проблему, я просто переименовал файл, а затем скопировал его обратно в исходное имя и местоположение. Использование оболочки Linux, которая была бы ...
 mv mydata.db temp.db
cp temp.db mydata.db
 

 


nXqd

+ 0 -
Как сказал Сеун Осева, иногда процесс зомби будет сидеть в терминале с заблокированным замком, даже если вы не думаете, что это возможно. Ваш сценарий запускается, аварийно завершает работу, и вы возвращаетесь к приглашению, но где-то в процессе вызова библиотеки появляется процесс зомби, и этот процесс заблокирован. Закрытие терминала, в котором вы были (в OSX), может работать. Перезагрузка будет работать. Вы можете искать процессы Python (например), которые ничего не делают, и убивать их.  


wisty

+ 0 -
вы можете попробовать это: .timeout 100, чтобы установить время ожидания. Я не знаю, что происходит в командной строке, но в C # .Net, когда я делаю это: "UPDATE table-name SET column-name = value;" Я получаю База данных заблокирована, но эта "UPDATE table-name SET column-name = value" все в порядке. Похоже, при добавлении; sqlite будет искать дальнейшие команды.  


robert

+ 226 -
В Windows вы можете попробовать эту программу http://www.nirsoft.net/utils/opened_files_view.html, чтобы узнать, как процесс обрабатывает файл БД. Попробуйте закрыть эту программу для разблокировки базы данных В Linux и macOS вы можете сделать что-то похожее, например, если ваш заблокированный файл - development.db:
  $ fuser development.db
Эта команда покажет, какой процесс блокирует файл:
  > development.db: 5430
Просто убей процесс ...
  убить -9 5430
... И ваша база данных будет разблокирована.


Kyle Cronin

+ 10 -
Должна быть внутренняя проблема базы данных ... Для меня это проявилось после попытки просмотреть базу данных с помощью менеджера SQLite ... Итак, если вы не можете найти другой процесс, подключенный к базе данных, и вы просто не можете это исправить, просто попробуйте это радикальное решение: Обеспечить экспорт ваших таблиц (вы можете использовать SQLite manager в Firefox) Если миграция изменила схему базы данных, удалите последнюю неудачную миграцию. Переименуйте ваш файл database.sqlite Выполните rake db: migrate, чтобы создать новую рабочую базу данных. Предоставить право доступа к базе данных для импорта таблицы Импортируйте ваши резервные копии таблиц Написать новую миграцию Выполните его с помощью rake db:migrate  


Heat Miser

+ 51 -
У меня была эта проблема только сейчас, при использовании базы данных SQLite на удаленном сервере, хранящейся при монтировании NFS. SQLite не удалось получить блокировку после того, как сеанс удаленной оболочки, который я использовал, потерпел крах, когда база данных была открыта. Предложенные выше рецепты восстановления не сработали (включая идею сначала переместить, а затем скопировать базу данных обратно). Но после копирования в систему, отличную от NFS, база данных стала пригодной для использования, и данные, по-видимому, не были потеряны.  Команда


Ben L

+ 2 -
lsof в моей среде Linux помогла мне понять, что процесс зависает, сохраняя файл открытым. Убил процесс и проблема была решена.  


converter42

+ 4 -
Я вызвал блокировку моего sqlite db из-за сбоя приложения во время записи. Вот как я это исправил:
 echo ".dump" | sqlite old.db | sqlite new.db
 

Взято из: http://random.kakaopor.hu/how-to-repair-an-sqlite-database  


Shawn Swaner

+ 0 -
У меня просто была такая же ошибка. После 5 минут поиска в Google я обнаружил, что не закрыл одну оболочку, которая использовала БД. Просто закройте его и попробуйте снова;)  


Stijn Sanders

+ 1 -
У меня была такая же проблема. Очевидно, что функция отката перезаписывает файл базы данных журналом, который совпадает с файлом базы данных, но без последнего изменения. Я реализовал это в своем коде ниже, и с тех пор он работал нормально, тогда как раньше мой код просто застревал в цикле, поскольку база данных оставалась заблокированной. Надеюсь это поможет мой код на питоне
 ##############
#### 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 )
 

 


TheSteven

+ 3 -
У меня есть такая проблема внутри приложения, при которой доступ к SQLite осуществляется из 2-х соединений - одно было только для чтения, а второе - для записи и чтения. Похоже, что соединение только для чтения заблокировало запись со второго соединения. Наконец, оказывается, что необходимо завершить или, по крайней мере, сбросить подготовленные операторы НЕМЕДЛЕННО после использования. До тех пор, пока готовый оператор не будет открыт, он вызвал, что база данных была заблокирована для записи. НЕ ЗАБЫВАЙТЕ ЗВОНИТЬ:
 sqlite_reset(xxx);
 

или же
 sqlite_finalize(xxx);
 




Kyle Cronin

+ 10 -
Одна из распространенных причин получения этого исключения - это когда вы пытаетесь выполнить операцию записи, в то же время удерживая ресурсы для операции чтения. Например, если вы ВЫБИРАЕТЕ из таблицы, а затем пытаетесь ОБНОВИТЬ что-то, что вы выбрали, не закрывая сначала свой ResultSet.  


Heat Miser

+ 51 -
Если вы хотите удалить заблокированную базу данных, выполните следующие действия: Скопируйте файл базы данных в другое место. Замените базу данных на скопированную базу данных. Это разыменовывает все процессы, которые обращались к вашему файлу базы данных.  


Ben L

+ 2 -
Я получил эту ошибку при использовании Delphi с компонентами LiteDAC. Оказалось, что это происходило только при запуске моего приложения из Delphi IDE, если для свойства подключения было установлено значение True для компонента подключения SQLite (в данном случае TLiteConnection).  


converter42

+ 4 -
Некоторые функции, такие как INDEX'ing, могут занимать очень много времени - и во время работы блокирует всю базу данных. В таких случаях он может даже не использовать файл журнала! Таким образом, лучший / единственный способ проверить, заблокирована ли ваша база данных, потому что процесс АКТИВНО записывает в нее (и, таким образом, вы должны оставить его в покое, пока он не завершит свою работу), - это md5 (или md5sum в некоторых системах) файл дважды , Если вы получаете другую контрольную сумму, база данных пишется, и вы действительно ДЕЙСТВИТЕЛЬНО не хотите уничтожать этот процесс, потому что вы можете легко получить поврежденную таблицу / базу данных, если вы это сделаете. Я еще раз повторю, потому что это важно - решение НЕ в том, чтобы найти программу блокировки и убить ее, а в том, чтобы найти, есть ли в базе данных блокировка записи по уважительной причине, и пойти дальше. Иногда правильное решение - просто перерыв на кофе. Единственный способ создать эту заблокированную, но не записываемую ситуацию - это если ваша программа выполняет BEGIN EXCLUSIVE, потому что она хотела внести какие-то изменения в таблицу или что-то еще, то по какой-либо причине никогда не отправляет потом END, и процесс никогда не завершается. Все три выполняемых условия весьма маловероятны в любом правильно написанном коде, и, таким образом, в 99 случаях из 100, когда кто-то хочет уничтожить -9 процесс блокировки, процесс блокировки фактически блокирует вашу базу данных по уважительной причине. Программисты обычно не добавляют условие BEGIN EXCLUSIVE, если в этом нет особой необходимости, потому что это предотвращает параллелизм и увеличивает количество жалоб пользователей. Сам SQLite добавляет его только тогда, когда это действительно необходимо (например, при индексации). Наконец, статус «заблокирован» не существует ВНУТРИ файла, как указано в нескольких ответах - он находится в ядре операционной системы. Процесс, который запустил BEGIN EXCLUSIVE, запросил у ОС блокировку файла. Даже если ваш эксклюзивный процесс потерпел крах, ваша ОС сможет выяснить, должна ли она поддерживать блокировку файла или нет !! Невозможно получить базу данных, которая заблокирована, но ни один процесс не блокирует ее активно !! Когда дело доходит до выяснения того, какой процесс блокирует файл, обычно лучше использовать lsof, а не fuser (это хорошая демонстрация того, почему: https://unix.stackexchange.com/questions/94316/fuser-vs-lsof- чтобы проверить-файлы в пользовании). Кроме того, если у вас есть DTrace (OSX), вы можете использовать iosnoop для файла.  


Shawn Swaner

+ 0 -
У меня была ошибка заблокированных баз данных в многопоточном приложении, которое выглядит как код результата SQLITE_BUSY, и я решил это, установив для sqlite3_busy_timeout что-то подходящее длинное, например 30000. (Кстати, как странно, что по 7-летнему вопросу никто не узнал об этом уже! SQLite действительно необычный и удивительный проект ...)  


Stijn Sanders

+ 1 -
Это потому, что в этой базе данных выполняется какой-то другой запрос. SQLite - это база данных, в которой запрос выполняется синхронно. Так что, если кто-то еще использует эту базу данных, тогда, если вы выполните запрос или транзакцию, она выдаст эту ошибку. Так что остановите тот процесс, который использует конкретную базу данных, а затем выполните ваш запрос.


Kyle Cronin

+ 10 -
Я получил эту ошибку в сценарии, немного отличающемся от описанного здесь. База данных SQLite покоилась в файловой системе NFS, используемой тремя серверами. На 2 серверах я смог успешно выполнить запросы к базе данных, на третьем мне показалось, что сообщение базы данных заблокировано. С этой третьей машиной не хватало места на /var. Каждый раз, когда я пытался выполнить запрос в ЛЮБОЙ базе данных SQLite, расположенной в этой файловой системе, я получал сообщение, что база данных заблокирована, а также эта ошибка в журналах:
  8 августа 10:33:38 server01 kernel: lockd: не может контролировать 172.22.84.87
И этот тоже:
  8 августа 10:33:38 server01 rpc.statd [7430]: Не удалось вставить: запись /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
После того, как космическая ситуация была обработана, все пришло в норму.  


Heat Miser

+ 51 -
Если вы пытаетесь разблокировать базу данных 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
 




Теги

sqlite