Python SQLite: база данных заблокирована
Я пытаюсь этот код:
import sqlite
connection = sqlite.connect('cache.db')
cur = connection.cursor()
cur.execute('''create table item
(id integer primary key, itemno text unique,
scancode text, descr text, price real)''')
connection.commit()
cur.close()
Я ловлю это исключение:
Traceback (most recent call last):
File "cache_storage.py", line 7, in <module>
scancode text, descr text, price real)''')
File "/usr/lib/python2.6/dist-packages/sqlite/main.py", line 237, in execute
self.con._begin()
File "/usr/lib/python2.6/dist-packages/sqlite/main.py", line 503, in _begin
self.db.execute("BEGIN")
_sqlite.OperationalError: database is locked
Разрешения для cache.db в порядке. Есть идеи?
23 ответа
Оказалось, что проблема произошла, потому что путь к файлу d b был на самом деле смонтированным каталогом samba. Я переместил это, и это начало работать.
Я предполагаю, что вы на самом деле используете sqlite3, хотя ваш код говорит иначе. Вот несколько вещей для проверки:
- Что у вас нет зависшего процесса в файле (unix:
$ fuser cache.db
нечего сказать) - В каталоге с cache.db нет файла cache.db-journal; это будет указывать на сбойный сеанс, который не был очищен должным образом.
- Попросите оболочку базы данных проверить себя:
$ sqlite3 cache.db "pragma integrity_check;"
- Резервное копирование базы данных
$ sqlite3 cache.db ".backup cache.db.bak"
- Удалите cache.db, так как в нем, вероятно, ничего нет (если вы только учитесь), и попробуйте снова свой код
- Посмотрите, работает ли резервная копия
$ sqlite3 cache.db.bak ".schema"
В противном случае прочитайте, что может пойти не так, и как повредить файлы базы данных.
Установите параметр времени ожидания в вашем соединении, как в:
connection = sqlite.connect('cache.db', timeout=10)
Я знаю, что это старый, но я все еще получаю проблему, и это первая ссылка на Google для этого. ОП сказал, что его проблема заключалась в том, что.db сидел на SMB-ресурсе, что было именно моей ситуацией. Мои десять минут исследования показывают, что это известный конфликт между sqlite3 и smb; Я нашел сообщения об ошибках, начиная с 2007 года.
Я решил это, добавив опцию "nobrl" к моей строке монтирования smb в / etc / fstab, так что теперь эта строка выглядит так:
//SERVER/share /mnt/point cifs credentials=/path/to/.creds,sec=ntlm,nobrl 0 0
Эта опция не позволяет вашему SMB-клиенту отправлять блокировки диапазона байтов на сервер. Я не слишком разбираюсь в деталях своего протокола SMB, но я лучше всего могу сказать, что этот параметр будет в основном интересен в многопользовательской среде, где кто-то другой может пытаться записать в тот же самый БД, что и вы. По крайней мере, для домашней установки это достаточно безопасно.
Мои соответствующие версии:
- Монетный двор 17.1 Ребекка
- SMB v4.1.6-Ubuntu
- Python v3.4.0
- SQLite v3.8.2
- Сетевой ресурс размещен на сервере Win12R2
Причина, по которой мое сообщение показывало сообщение "Блокировка", на самом деле была связана с тем, что я открыл IDE SQLite3 на моем Mac, и именно по этой причине оно было заблокировано. Я предполагаю, что я играл с БД в IDE и не сохранил изменения, и поэтому была установлена блокировка.
Короче говоря, убедитесь, что на БД нет несохраненных изменений, а также что он не используется в других местах.
В Linux вы можете сделать нечто подобное, например, если ваш заблокированный файл - development.db:
$ fuser development.db Эта команда покажет, какой процесс блокирует файл:
development.db: 5430 Просто убей процесс...
kill -9 5430... И ваша база данных будет разблокирована.
Поскольку эта проблема по-прежнему остается самой популярной в Google, позвольте мне добавить возможную причину. Если вы редактируете структуру своей базы данных и не зафиксировали изменения, база данных блокируется до тех пор, пока вы не подтвердите или не отмените ее.
(Вероятно, необычно, но я разрабатываю приложение, поэтому код и база данных разрабатываются одновременно)
Вот удобный обходной путь для одновременного доступа:
while True:
connection = sqlite3.connect('user.db', timeout=1)
cursor = connection.cursor()
try:
cursor.execute("SELECT * FROM queue;")
result = cursor.fetchall()
except sqlite3.OperationalError:
print("database locked")
num_users = len(result)
# ...
База данных заблокирована другим процессом, который пишет в нее. Вы должны подождать, пока другая транзакция не будет совершена. Смотрите документацию по connect()
Вам следует проверить, не работает ли в вашей базе данных платформа администрирования и разработки СУБД (например, pgAdmin), так как это, вероятно, самая распространенная причина этой ошибки. Если есть - зафиксируйте внесенные изменения и проблема исчезнет.
- Ваш
cache.db
в настоящее время используется другим процессом. - Остановите этот процесс и попробуйте снова, он должен работать.
Одной из возможных причин блокировки базы данных, с которой я столкнулся с SQLite, является то, что я пытался получить доступ к строке, которая была написана одним приложением и одновременно прочитана другим. Возможно, вы захотите установить время ожидания занятости в вашей оболочке SQLite, которое будет вращаться и ожидать освобождения базы данных (в исходном API- интерфейсе C++ функция sqlite3_busy_timeout). Я обнаружил, что 300 мс было достаточно в большинстве случаев.
Но я сомневаюсь, что это проблема, основанная на вашем посте. Попробуйте сначала другие рекомендации.
Еще одна возможность, которая произошла со мной, я дважды открывал базу данных, первое открытие заблокировало второе. Проверьте, что вы не делаете этого.
У меня такая же проблема: sqlite3.IntegrityError
Как упоминалось во многих ответах, проблема в том, что соединение не было правильно закрыто.
В моем случае я имел try
except
блоки. Я обращался к базе данных в try
блок и когда возникло исключение, я хотел сделать что-то еще в except
блок.
try:
conn = sqlite3.connect(path)
cur = conn.cursor()
cur.execute('''INSERT INTO ...''')
except:
conn = sqlite3.connect(path)
cur = conn.cursor()
cur.execute('''DELETE FROM ...''')
cur.execute('''INSERT INTO ...''')
Однако, когда возникло исключение, соединение от try
Блок не был закрыт.
Я решил это используя with
заявления внутри блоков.
try:
with sqlite3.connect(path) as conn:
cur = conn.cursor()
cur.execute('''INSERT INTO ...''')
except:
with sqlite3.connect(path) as conn:
cur = conn.cursor()
cur.execute('''DELETE FROM ...''')
cur.execute('''INSERT INTO ...''')
в моем случае сообщение 'заблокировано' произошло из-за несохраненных изменений, которые я сделал в DB BROWSER(SQL LITE), мне пришлось сохранить их, а затем, когда я снова выполнил свой скрипт, проблема была решена, надеюсь, это поможет кому-то как в моем случае.
У меня была эта проблема при работе с Pycharm и с базой данных, которая была первоначально предоставлена мне другим пользователем.
Итак, вот как я решаю это в моем случае:
- Закрыты все вкладки в Pycharm, которые работают с проблемной базой данных.
- Остановите все запущенные процессы из нижней части красного квадрата в верхнем правом углу Pycharm.
- Удалить проблемную базу данных из каталога.
- Загрузите снова исходную базу данных. И это снова сработало.
О, ваш откат дал это: у вас конфликт версий. Вы установили некоторую старую версию sqlite в локальный каталог dist-packages, когда у вас уже есть sqlite3, включенный в ваш дистрибутив python2.6, и вам не требуется и, вероятно, вы не можете использовать старую версию sqlite. Первая попытка:
$ python -c "import sqlite3"
и если это не приводит к ошибке, удалите ваш dist-пакет:
easy_install -mxN sqlite
а потом import sqlite3
в своем коде вместо этого и получайте удовольствие.
В моем случае ошибка произошла, когда много одновременных процессов пытались читать / писать в одну и ту же таблицу. Я использовал повтор, чтобы обойти проблему
def _retry_if_exception(exception):
return isinstance(exception, Exception)
@retry(retry_on_exception=_retry_if_exception,
wait_random_min=1000,
wait_random_max=5000,
stop_max_attempt_number=5)
def execute(cmd, commit=True):
c.execute(cmd)
c.conn.commit()
У меня тоже была эта проблема. Я пытался ввести данные в базу данных без сохранения внесенных в нее изменений. после того как я сохранил изменения работали
Простое решение: проверьте один раз, открыли ли вы базу данных в другом окне или в другом терминале. Это также блокирует вашу базу данных. В моем случае я закрыл все остальные терминалы, которые блокировали базу данных (вкладка терминала в Pycharm). Также проверьте каждую вкладку терминалов вашей IDE, если есть терминал, который оставил базу данных открытой. exit() все терминалы должны работать, разблокируя базу данных.
Я использую sqlite3, я решаю проблему блокировки, добавляя уровень изоляции транзакций conn= sqlite3.connect('image.db',isolation_level=None,timeout=0.01);
Даже когда у меня был только один писатель и один читатель, моя проблема заключалась в том, что одно из чтений занимало слишком много времени: дольше, чем предусмотренный тайм-аут в 5 секунд. Таким образом, время записи истекло и возникла ошибка.
Поэтому будьте осторожны при чтении всех записей из базы данных, особенно из той, размер таблицы которой со временем увеличивается.
Я обнаружил, что это сработало для моих нужд. (блокировка резьбы) YMMV
conn = sqlite3.connect(база данных, тайм-аут =10)
https://docs.python.org/3/library/sqlite3.html
sqlite3.connect(база данных [, тайм-аут, обнаружение_типов, уровень_изоляции, имя_проверки_потока, фабрика, cached_statements, uri])
Когда к базе данных обращается несколько подключений и один из процессов изменяет базу данных, база данных SQLite блокируется до тех пор, пока транзакция не будет зафиксирована. Параметр тайм-аута указывает, как долго соединение должно ждать снятия блокировки до возникновения исключения. По умолчанию для параметра тайм-аута установлено значение 5,0 (пять секунд).