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
разрешения для кэша.БД ОК. Есть идеи?
16 ответов
Я предполагаю, что вы на самом деле используете sqlite3, хотя ваш код говорит иначе. Вот некоторые вещи, чтобы проверить:
- что у вас нет зависшего процесса, сидящего на файле (unix:
$ fuser cache.db
ничего не скажу) - кэша нет.db-файл журнала в каталоге с кэшем.db; это указывает на сбой сеанса, который не был очищен должным образом.
- попросите оболочку базы данных проверить себя:
$ sqlite3 cache.db "pragma integrity_check;"
- резервное копирование база данных
$ sqlite3 cache.db ".backup cache.db.bak"
- удалить кэш.db, поскольку у вас, вероятно, ничего нет (если вы только учитесь) и повторите попытку кода
- посмотрите, работает ли резервная копия
$ sqlite3 cache.db.bak ".schema"
в противном случае прочитайте Вещи, Которые Могут Пойти Не Так и как повредить файлы базы данных
установите параметр timeout в вызове connect, как в:
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
оказалось, что проблема произошла, потому что путь к файлу БД на самом деле был смонтирован в samba. Я передвинул его, и он начал работать.
в Linux вы можете сделать что-то подобное, например, если заблокированный файл-это развитие.дБ:
$ Термоблок развития.децибел Эта команда покажет какой процесс блокирует файл:
развитие.дБ: 5430 Просто убейте процесс...
убить -9 5430 ...И ваша база данных будет разблокирована.
причина, по которой я показывал сообщение "Lock", На самом деле была связана с тем, что я открыл sqlite3 IDE на моем mac, и именно поэтому он был заблокирован. Я предполагаю, что я играл с БД в среде IDE и не сохранил изменения, и поэтому была помещена блокировка.
Короче говоря, проверьте, что в БД нет несохраненных изменений, а также что он не используется в другом месте.
вот аккуратный обходной путь для одновременного доступа:
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), так как это, вероятно, самая популярная причина этой ошибки. Если есть-зафиксируйте изменения, и проблема исчезнет.
одна из возможных причин блокировки базы данных, с которой я столкнулся с SQLite, - это когда я пытался получить доступ к строке, написанной одним приложением, и читать другим одновременно. Вы можете установить тайм-аут занятости в оболочке SQLite, которая будет вращаться и ждать, пока база данных станет свободной (в исходном api c++ функция sqlite3_busy_timeout). Я обнаружил, что 300ms было достаточно в большинстве случаев.
но я сомневаюсь, что это проблема, основанные на ваше сообщение. Сначала попробуйте другие рекомендации.
поскольку это все еще лучший хит Google для этой проблемы, позвольте мне добавить возможную причину. Если вы редактируете структуру базы данных и не зафиксировали изменения, база данных блокируется до фиксации или возврата.
(вероятно, необычно, но я разрабатываю приложение, поэтому код и база данных разрабатываются одновременно)
- код
cache.db
в настоящее время используется другим процессом. - остановите этот процесс и повторите попытку, он должен работать.
У меня была эта проблема во время работы с Pycharm и с базой данных, которая была первоначально предоставлена мне другим пользователем.
Итак, вот как я решаю это в моем случае:
- закрыл все вкладки в Pycharm, которые работают с проблемной базой данных.
- остановите все запущенные процессы из Боттона Красного квадрата в правом верхнем углу Pycharm.
- удалите проблемную базу данных из каталога.
- загрузить снова исходная база данных. И это снова сработало.
о, Ваш трейсбек выдал его: у вас есть конфликт версий. Вы установили некоторую старую версию sqlite в локальном каталоге dist-пакетов, когда у вас уже есть sqlite3, включенный в python2.6 дистрибутив и не нужен и, вероятно, не может использовать старую версию sqlite. Первая попытка:
$ python -c "import sqlite3"
и если это не дает вам ошибку, удалите ваш dist-пакет:
easy_install -mxN sqlite
а то import sqlite3
в коде вместо этого и получать удовольствие.
у меня была та же проблема: 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 ...''')
У меня также была эта проблема. Я пытался ввести данные в базу данных без сохранения изменений, которые я сделал в ней. после того, как я сохранил изменения работал