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 в порядке. Любые идеи?


person Soid    schedule 29.04.2010    source источник


Ответы (21)


Я предполагаю, что вы действительно используете sqlite3, хотя в вашем коде указано иное. Вот что нужно проверить:

  1. Что у вас нет зависшего процесса, сидящего в файле (unix: $ fuser cache.db ничего не должен сказать)
  2. В каталоге с cache.db нет файла cache.db-journal; это будет означать сбой сеанса, который не был очищен должным образом.
  3. Попросите оболочку базы данных проверить себя: $ sqlite3 cache.db "pragma integrity_check;"
  4. Сделайте резервную копию базы данных $ sqlite3 cache.db ".backup cache.db.bak"
  5. Удалите cache.db, так как у вас, вероятно, ничего нет (если вы только учитесь), и попробуйте свой код еще раз.
  6. Посмотрите, работает ли резервная копия $ sqlite3 cache.db.bak ".schema"

В противном случае прочтите Что может пойти не так и Как испортить файлы базы данных

person msw    schedule 29.04.2010
comment
Я оставляю этот ответ в силе, поскольку в целом он полезен, но мой другой ответ, вероятно, правильный. - person msw; 30.04.2010
comment
Еще лучше: добавьте свой другой ответ в качестве седьмого, что нужно проверить;) - person tzot; 30.04.2010
comment
Спасибо за ваш ответ. У меня нет данных в этой базе данных (cache.db имеет размер 0 байт), поэтому резервировать ее не нужно. 1) fuser ничего не выводит 2) нет файла db-journal перед запуском 3) sqlite3 cache.db pragma integration_check; говорит ОК 5) Я много раз пытался удалить и переименовать файл cache.db ;-) Теперь я протестировал его на другой машине, но с той же серверной версией ОС Ubuntu 9.10, и получил тот же результат. Эта ошибка возникает, когда я устанавливаю пакет python-sqlite. - person Soid; 30.04.2010

Установите параметр тайм-аута в вызове подключения, как показано ниже:

connection = sqlite.connect('cache.db', timeout=10)
person Anthony DeRosa    schedule 23.12.2011
comment
Похоже, что значение по умолчанию составляет 5 секунд на docs.python.org/2 /library/sqlite3.html#sqlite3.connect - person storm_m2138; 25.05.2017
comment
Когда ваш вызов для подключения не работает с сообщением об ошибке, база данных заблокирована, это потому, что другое соединение уже обращается к базе данных. Указав тайм-аут (в данном случае timeout = 10), вы даете другому потоку время для завершения транзакции и закрытия соединения, после чего ваше соединение может продолжиться. Без тайм-аута попытка подключения немедленно завершится ошибкой. - person Anthony DeRosa; 08.04.2018

Я знаю, что это устарело, но проблема все еще возникает, и это первая ссылка на нее в Google. OP сказал, что его проблема заключалась в том, что .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.
person sprint_ska    schedule 17.05.2015
comment
У меня такая же проблема, что он не работает на общем ресурсе SMB. Я попробовал ваше решение с добавлением nobrl, но все равно с той же ошибкой. Локально работает нормально. - person Sandro4912; 05.08.2020

Причина, по которой у меня отображалось сообщение «Заблокировано», на самом деле была связана с тем, что я открыл IDE SQLite3 на моем Mac, и именно по этой причине она была заблокирована. Я предполагаю, что я играл с БД в среде IDE и не сохранил изменения, поэтому была установлена ​​блокировка.

Короче говоря, убедитесь, что в базе данных нет несохраненных изменений, а также что она не используется где-либо еще.

person Erion S    schedule 12.10.2015
comment
Этот укусил меня. Несохраненные изменения в браузере БД SQLIte - person ryentzer; 07.03.2018

В Linux вы можете сделать что-то подобное, например, если ваш заблокированный файл - development.db:

$ fuser development.db Эта команда покажет, какой процесс блокирует файл:

development.db: 5430 Просто убейте процесс ...

kill -9 5430 ... И ваша база будет разблокирована.

person arunjos007    schedule 15.07.2015

Оказалось, что проблема возникла из-за того, что путь к файлу db был фактически установленным каталогом samba. Я переместил его, и это начало работать.

person Soid    schedule 10.09.2012

Вот изящный обходной путь для одновременного доступа:

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)
# ...
person Jithin    schedule 15.06.2010
comment
Вы забыли continue? - person remram; 02.07.2018
comment
Дайте ему break - person Eric; 22.03.2019
comment
btw timeout=1 является лишним: в большинстве случаев достаточно тайм-аута по умолчанию, равного 5 секундам. - person Eric; 22.03.2019

Поскольку это по-прежнему самая популярная проблема Google, позвольте мне добавить возможную причину. Если вы редактируете структуру своей базы данных и не зафиксировали изменения, база данных заблокирована до тех пор, пока вы не зафиксируете или не вернетесь.

(Возможно, необычно, но я разрабатываю приложение, поэтому код и база данных разрабатываются одновременно)

person Jeff D.    schedule 09.12.2016

База данных заблокирована другим процессом, который в нее записывает. Вам нужно дождаться подтверждения другой транзакции. См. Документацию по connect ()

person Florian Diesch    schedule 29.04.2010

Вы должны проверить, нет ли платформы для администрирования и разработки СУБД, работающей с вашей базой данных (например, pgAdmin), поскольку это, вероятно, самая популярная причина этой ошибки. Если есть - зафиксируйте сделанные изменения и проблема исчезнет.

person PyFox    schedule 28.03.2018

Одна из возможных причин блокировки базы данных, с которой я столкнулся с SQLite, - это когда я пытался получить доступ к строке, которая была записана одним приложением и прочитана другим одновременно. Вы можете установить тайм-аут занятости в вашей оболочке SQLite, который будет вращаться и ждать, пока база данных станет свободной (в исходном c ++ api функция sqlite3_busy_timeout). Я обнаружил, что в большинстве случаев достаточно 300 мс.

Но я сомневаюсь, что это проблема, исходя из вашего сообщения. Сначала попробуйте другие рекомендации.

person J. Polfer    schedule 29.04.2010

У меня была такая же проблема: 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 ...''')
person J0ANMM    schedule 20.09.2016
comment
когда ты commit? - person Mausy5043; 08.09.2019

  1. Ваш cache.db в настоящее время используется другим процессом.
  2. Остановите этот процесс и попробуйте еще раз, он должен работать.
person Avinash Jeeva    schedule 17.01.2017

О, ваша трассировка выдала это: у вас конфликт версий. Вы установили старую версию sqlite в свой локальный каталог dist-packages, когда у вас уже есть sqlite3, включенный в ваш дистрибутив python2.6, и вы не нуждаетесь и, вероятно, не можете использовать старую версию sqlite. Первая попытка:

$ python -c "import sqlite3"

и если это не приводит к ошибке, удалите дистрибутив :

easy_install -mxN sqlite

а затем import sqlite3 в вашем коде и получайте удовольствие.

person msw    schedule 29.04.2010
comment
Я проверил использование sqlite3, и он работает по-другому. Он создает файл db-journal и ждет. Затем база данных снова блокируется, а sqlite без 3 ничего не ждет. - person Soid; 30.04.2010

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

Вот как я решаю это в моем случае:

  1. Закрыты все вкладки в Pycharm, которые работают с проблемной базой данных.
  2. Остановите все запущенные процессы с помощью красного квадрата в правом верхнем углу Pycharm.
  3. Удалите проблемную базу данных из каталога.
  4. Загрузите снова исходную базу данных. И это снова сработало.
person T. Iva    schedule 06.05.2018

У меня тоже была такая проблема. Я пытался ввести данные в базу данных без сохранения внесенных в нее изменений. после того, как я сохранил изменения, сработало

person Adriano Oliveira    schedule 10.02.2018
comment
Используйте комментарии для этого типа коротких ответов. Если вы отвечаете что-нибудь поясняющее, добавьте дополнительную информацию, примеры сайтов и предоставьте ссылки. - person Munim Munna; 10.02.2018

в моем случае ошибка произошла, когда много одновременных процессов пытались читать / писать в одну и ту же таблицу. Я использовал повторную попытку, чтобы обойти проблему

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()
person cannie    schedule 12.12.2019

Даже когда у меня был только один писатель и один читатель, моя проблема заключалась в том, что одно из чтений занимало слишком много времени: больше, чем оговоренный тайм-аут в 5 секунд. Таким образом, время записи истекло и возникла ошибка.

Поэтому будьте осторожны при чтении всех записей из базы данных, особенно из той, размер таблицы которой со временем увеличивается.

person zbz.lvlv    schedule 12.05.2020

Простое решение: проверьте один раз, открыли ли вы базу данных в другом окне или в другом терминале. Это также блокирует вашу базу данных. В моем случае я закрыл все остальные терминалы, которые блокировали базу данных (вкладка терминала в Pycharm). Проверьте каждую вкладку терминалов вашей IDE, а также, есть ли терминал, который оставил базу данных открытой. exit () все терминалы должны работать, разблокируя базу данных.

person Guru Bhandari    schedule 23.10.2020

Я обнаружил, что это сработало для моих нужд (блокировка потоков):

conn = sqlite3.connect(database, timeout=10)

Документы

sqlite3.connect(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri])

Когда к базе данных обращается несколько подключений, и один из процессов изменяет базу данных, база данных SQLite блокируется до тех пор, пока транзакция не будет зафиксирована. Параметр тайм-аута указывает, как долго соединение должно ждать снятия блокировки до возникновения исключения. По умолчанию для параметра тайм-аута установлено значение 5,0 (пять секунд).

person CodingMatters    schedule 18.08.2020

в моем случае сообщение 'заблокировано' произошло из-за несохраненных изменений, которые я сделал в DB BROWSER (SQL LITE), мне пришлось сохранить их, а затем, когда я снова выполнил свой скрипт, проблема была решена, надеюсь, это поможет кому-то как в моем случае.

person Lcool    schedule 30.04.2021