Подтвердить что ты не робот

Операционная защита: база данных заблокирована

Я сделал несколько повторяющихся операций в своем приложении (тестирование), и внезапно Im получил странную ошибку:

OperationalError: database is locked

Я перезапустил сервер, но ошибка сохраняется. О чем это может быть?

4b9b3361

Ответ 1

Из django doc:

SQLite должен быть легким базы данных и, следовательно, не может поддерживать высокий уровень concurrency. Операционная защита: база данных заблокирована ошибки указывают, что ваше приложение испытывает больше concurrency, чем sqlite может обрабатывать по умолчанию конфигурации. Эта ошибка означает, что один поток или процесс имеет эксклюзивный блокировка соединения с базой данных и другой поток, ожидающий блокировка будет выпущена.

Оболочка Python SQLite имеет значение по умолчанию время ожидания, определяющее, как долго второй поток можно ждать на замке перед тем, как он истечет и повышает базу данных OperationalError: ошибка заблокирована.

Если вы получаете эту ошибку, вы можете решить его:

Переход на другой сервер базы данных. В какой-то момент SQLite становится слишком "lite" для реальных приложений, и эти типы ошибок concurrencyукажите, что вы достигли этой точки.

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

Увеличьте значение таймаута по умолчанию на установка опции базы данных таймаута optionoption

http://docs.djangoproject.com/en/dev/ref/databases/#database-is-locked-errorsoption

Ответ 2

Практическая причина этого часто заключается в том, что оболочки python или django открыли запрос в БД и не были закрыты должным образом; убийство вашего доступа к терминалу часто освобождает его. У меня была эта ошибка при запуске тестов командной строки.

Изменить: я получаю периодические upvotes на этом. Если вы хотите убить доступ без перезагрузки терминала, то из командной строки вы можете сделать:

from django import db
db.connections.close_all()

Ответ 3

В моем случае это было потому, что я открываю базу данных из браузера SQLite. Когда я закрываю его из браузера, проблема исчезла.

Ответ 4

Я не согласен с ответом @Patrick, который, цитируя этот документ, неявно связывает проблему OP (Database is locked) с этим:

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

Это немного "слишком просто", чтобы обвинить SQlite в этой проблеме. Если у вас не очень загруженный сервер с тысячами подключений в одну секунду, причиной этой ошибки Database is locked, вероятно, является скорее неправильное использование API, чем проблема, свойственная SQlite, которая была бы "слишком легкой". Вот дополнительная информация о Пределах реализации для SQLite.


Теперь решение:

У меня была та же проблема, когда я использовал два сценария, использующих одну и ту же базу данных одновременно:

  • один обращался к БД с помощью операций записи
  • другой обращался к БД только для чтения

Решение: всегда выполняйте cursor.close() как можно скорее после выполнения запроса (даже только для чтения).

Вот более подробная информация.

Ответ 5

Как уже говорили другие, есть другой процесс, который использует файл SQLite и не закрыл соединение. Если вы используете Linux, вы можете увидеть, какие процессы используют файл (например, db.sqlite3), с помощью команды fuser:

$ sudo fuser -v db.sqlite3
                     USER        PID ACCESS COMMAND
/path/to/db.sqlite3:
                     user    955 F.... apache2

Если вы хотите остановить процессы, чтобы снять блокировку, используйте fuser -k который отправляет сигнал KILL всем процессам, обращающимся к файлу:

sudo fuser -k db.sqlite3

Обратите внимание, что это опасно, так как это может остановить процесс веб-сервера на рабочем сервере.

Спасибо @cz-game за указание на fuser !

Ответ 6

Для меня это решается, как только я закрыл оболочку django, которая была открыта с помощью python manage.py shell

Ответ 7

Я столкнулся с этим сообщением об ошибке в ситуации, которая (явно) не указана в справочной информации, указанной в ответе Патрика.

Когда я использовал transaction.atomic(), чтобы обернуть вызов в FooModel.objects.get_or_create(), и вызывал этот код одновременно из двух разных потоков, только один поток завершился успешно, а другой получил ошибку "база данных заблокирована". Изменение параметра базы данных тайм-аута не повлияло на поведение.

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

Я решил проблему, используя объект threading.RLock вместо transaction.atomic(), когда мое приложение Django работает с бэкэндом sqlite. Это не совсем эквивалентно, поэтому вам может потребоваться сделать что-то еще в вашем приложении.

Вот мой код, который запускает FooModel.objects.get_or_create одновременно из двух разных потоков, в случае, если это полезно:

from concurrent.futures import ThreadPoolExecutor

import configurations
configurations.setup()

from django.db import transaction
from submissions.models import ExerciseCollectionSubmission

def makeSubmission(user_id):
    try:
        with transaction.atomic():
            e, _ = ExerciseCollectionSubmission.objects.get_or_create(
                student_id=user_id, exercise_collection_id=172)
    except Exception as e:
        return f'failed: {e}'

    e.delete()

    return 'success'


futures = []

with ThreadPoolExecutor(max_workers=2) as executor:
    futures.append(executor.submit(makeSubmission, 296))
    futures.append(executor.submit(makeSubmission, 297))

for future in futures:
    print(future.result())

Ответ 8

Это также может произойти, если вы подключены к своей базе данных sqlite через плагин dbbrowser через pycharm. Отключение решит проблему

Ответ 9

У меня такая же ошибка! Одной из причин было закрытие соединения с БД. Поэтому проверьте наличие незакрытых соединений с БД. Кроме того, проверьте, если вы зафиксировали базу данных, прежде чем закрывать соединение.

Ответ 10

В моем случае я не сохранил операцию базы данных, которую выполнял в браузере SQLite. Сохранение решило проблему.

Ответ 11

ОБНОВЛЕНИЕ django версия 2.1.7

Я получил эту ошибку sqlite3.OperationalError: database is locked с помощью pytest с django.

Решение:

Если мы используем @pytest.mark.django_db декоратор. Что он делает, так это создает in-memory-db для тестирования.

По имени: file:memorydb_default?mode=memory&cache=shared Мы можем получить это имя с помощью:

from django.db import connection
db_path = connection.settings_dict['NAME']

Чтобы получить доступ к этой базе данных, а также отредактировать ее, выполните:

Подключиться к базе данных:

with sqlite3.connect(db_path, uri=True) as conn:
    c = conn.cursor()

Используйте uri=True чтобы указать файл диска, который является базой данных SQLite, которую нужно открыть.

Чтобы избежать ошибки, активируйте транзакции в декораторе:

@pytest.mark.django_db(transaction=True)

Финальная функция:

from django.db import connection

@pytest.mark.django_db(transaction=True)
def test_mytest():
    db_path = connection.settings_dict['NAME']
    with sqlite3.connect(db_path, uri=True) as conn:
        c = conn.cursor()
        c.execute('my amazing query')
        conn.commit()
    assert ... == ....

Ответ 12

попробуйте выполнить эту команду:

sudo fuser -k 8000/tcp