programing

작업 오류: 데이터베이스가 잠겼습니다.

mailnote 2023. 7. 20. 22:06
반응형

작업 오류: 데이터베이스가 잠겼습니다.

응용 프로그램에서 반복적인 작업(테스트)을 수행했는데 갑자기 이상한 오류가 발생합니다.

OperationalError: database is locked

서버를 다시 시작했지만 오류가 계속 발생합니다.도대체 무슨 일입니까?

장고 문서에서:

SQLite는 경량 데이터베이스이므로 높은 수준의 동시성을 지원할 수 없습니다.작동 오류: 데이터베이스 잠금 오류는 응용 프로그램이 기본 구성에서 처리할 수 있는 것보다 더 많은 동시성을 경험하고 있음을 나타냅니다.이 오류는 하나의 스레드 또는 프로세스가 데이터베이스 연결에 대한 배타적 잠금을 가지고 있고 다른 스레드가 잠금 해제를 기다리는 동안 시간 초과되었음을 의미합니다.

Python의 SQLite 래퍼에는 시간 초과되기 전에 두 번째 스레드가 잠금에서 대기할 수 있는 시간을 결정하는 기본 시간 초과 값이 있으며 OperationalError: database locked 오류가 발생합니다.

이 오류가 발생하면 다음 방법으로 해결할 수 있습니다.

  • 다른 데이터베이스 백엔드로 전환하는 중입니다.특정 시점에서 SQLite는 실제 애플리케이션에 너무 "lite"가 되고 이러한 종류의 동시성 오류는 해당 시점에 도달했음을 나타냅니다.
  • 코드를 다시 작성하여 동시성을 줄이고 데이터베이스 트랜잭션의 수명을 단축합니다.
  • 시간 초과 데이터베이스 옵션을 설정하여 기본 시간 초과 값 증가

http://docs.djangoproject.com/en/dev/ref/databases/ #backup-is-locked-dis-locked-locked 옵션

제 경우에는 SQLite Browser에서 데이터베이스를 열기 때문입니다.브라우저에서 닫으면 문제가 사라집니다.

OP의를 암시적으로 연결하는 하지 않습니다.Database is locked로 이동합니다.

다른 데이터베이스 백엔드로 전환하는 중입니다.특정 시점에서 SQLite는 실제 애플리케이션에 너무 "lite"가 되고 이러한 종류의 동시성 오류는 해당 시점에 도달했음을 나타냅니다.

이 문제로 SQLite를 기소하기에는 "너무 쉽다"(정확히 사용하면 매우 강력하다. 작은 데이터베이스의 장난감일 뿐만 아니라 재미있는 사실:An SQLite database is limited in size to 140 terabytes ).

수천 개의 연결을 동시에 수행하는 매우 바쁜 서버를 사용하지 않는 한, 이 오류의 원인은 SQLite 고유의 "너무 가볍다"는 문제라기보다는 API를 잘못 사용했기 때문일 것입니다.다음은 SQLite의 구현 제한에 대한 자세한 내용입니다.


이제 해결책:

동일한 데이터베이스를 사용하여 두 스크립트를 동시에 사용할 때도 동일한 문제가 발생했습니다.

  • 하나는 쓰기 작업으로 DB에 액세스하는 것이었습니다.
  • 다른 하나는 읽기 전용으로 DB에 액세스하고 있었습니다.

해결책: 항상 (읽기 전용) 쿼리를 수행한 후 가능한 한 빨리 수행합니다.

자세한 내용은 다음과 같습니다.

이에 대한 실질적인 이유는 종종 파이썬 또는 장고 셸이 DB에 대한 요청을 열었지만 제대로 닫히지 않았기 때문입니다. 터미널 액세스를 종료하면 종종 DB가 해방됩니다.오늘 명령줄 테스트를 실행할 때 이 오류가 발생했습니다.

편집: 저는 이것에 대한 정기적인 투표를 받습니다.터미널을 재부팅하지 않고 액세스를 중지하려면 명령줄에서 다음 작업을 수행할 수 있습니다.

from django import db
db.connections.close_all()

다른 사람들이 말했듯이 SQLite 파일을 사용하고 있지만 연결을 닫지 않은 다른 프로세스가 있습니다.할 수 예: " 리스를사예경는사프확수있다인할습니를스로세는하용을눅용").db.sqlite3fuser다음과 같이 명령합니다.

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

하려면 잠을해는프를중스사다다면용니합음을려지하로금세제하▁to▁if다▁use▁processes사니▁the합,용▁lock▁the▁you다음을 사용합니다.fuser -k이는 전송합니다.KILL파일에 액세스하는 모든 프로세스에 대한 신호:

sudo fuser -k db.sqlite3

이렇게 하면 프로덕션 서버에서 웹 서버 프로세스가 중지될 수 있으므로 위험합니다.

@@cz-game에 에 감사드립니다.fuser!

패트릭의 답변에 링크된 도움말 정보에 의해 (명백하게) 해결되지 않은 상황에서 이 오류 메시지가 발생했습니다.

가 경한우용을 했을 때.transaction.atomic()를 화를끝다로 FooModel.objects.get_or_create()그리고 두 개의 다른 스레드에서 동시에 코드를 호출하면 한 스레드만 성공하고 다른 스레드는 "스레드 잠금" 오류가 발생합니다.시간 초과 데이터베이스 옵션을 변경해도 동작에 영향을 주지 않습니다.

이것은 sqlite가 여러 개의 동시 작성자를 처리할 수 없기 때문에 애플리케이션이 스스로 쓰기를 직렬화해야 하기 때문이라고 생각합니다.

는 저는문해습다니결했를제▁a▁using를 사용하여 문제를 해결했습니다.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())

WSL(\wsl$...)에 저장된 데이터베이스 파일을 사용하고 Windows python 인터프리터를 실행할 때 이 오류가 발생했습니다.

WSL 트리에 데이터베이스를 저장할 수 없거나 배포자에서 Linux 기반 인터프리터를 사용할 수 있습니다.

SQLite Browser에서 데이터베이스를 열고 변경사항을 쓰는 것을 잊어버려서 플라스크 앱에서 이 문제에 직면했습니다.

SQLite Browser에서도 변경한 내용이 있으면 쓰기 변경을 클릭하면 모든 것이 정상입니다.

enter image description here

pycharm을 통해 dbbrowser 플러그인을 통해 sqlite db에 연결된 경우에도 이 문제가 발생할 수 있습니다.연결을 끊으면 문제가 해결됩니다.

저는 일단 장고 쉘을 닫으면 해결됩니다.python manage.py shell

저도 같은 오류가 있어요!그 이유 중 하나는 DB 연결이 닫히지 않았기 때문입니다.따라서 닫히지 않은 DB 연결을 확인합니다.또한 연결을 닫기 전에 DB를 커밋했는지 확인합니다.

장고(v3.0.3)의 첫 번째 인스턴스화 직후에도 비슷한 오류가 발생했습니다.여기에 제시된 모든 권장 사항은 다음을 제외하고는 작동하지 않았습니다.

  • 했습니다.db.sqlite3파일을 보관하고 데이터를 분실할 수 있습니다.
  • python manage.py makemigrations
  • python manage.py migrate

그나저나, 만약 당신이 포스트그리를 테스트하고 싶다면.SQL:

docker run --rm --name django-postgres \
  -e POSTGRES_PASSWORD=mypassword \
  -e PGPORT=5432 \
  -e POSTGRES_DB=myproject \
  -p 5432:5432 \
  postgres:9.6.17-alpine

변할내용을 합니다.settings.py이것을 덧붙이자면DATABASES:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'myproject',
        'USER': 'postgres',
        'PASSWORD': 'mypassword',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

...데이터베이스 어댑터 추가:

pip install psycopg2-binary

그러면 일반적으로:

python manage.py makemigrations
python manage.py migrate

데이터베이스가 다른 DB 브라우저에서 열려 있는지 확인합니다.

다른 응용 프로그램에서 열려 있는 경우 응용 프로그램을 닫고 프로그램을 다시 실행합니다.

데이터베이스를 닫고(중지) 열기(시작)만 하면 됩니다.이것으로 저의 문제가 해결되었습니다.

저는 이것이 제 요구에 맞는다는 것을 알았습니다.(잠금 해제) YMMV conn = sqlite3.connect (일시 중지, 시간 초과=10)

https://docs.python.org/3/library/sqlite3.html

sqlite3.connect(sqlite[, 시간 초과, detect_types, isolation_level, check_same_dll, 공장, cached_statements, uri])

여러 연결을 통해 데이터베이스에 액세스할 때 프로세스 중 하나가 데이터베이스를 수정하면 해당 트랜잭션이 커밋될 때까지 SQLite 데이터베이스가 잠깁니다.시간 초과 매개 변수는 예외가 발생할 때까지 연결이 잠금이 해제될 때까지 기다리는 시간을 지정합니다.시간 초과 매개 변수의 기본값은 5.0(5초)입니다.

제 경우 수동으로 저장한 새 레코드를 추가했고 셸을 통해 다시 새 레코드를 추가하려고 했습니다. 이번에는 완벽하게 작동합니다.

In [7]: from main.models import Flight

In [8]: f = Flight(origin="Florida", destination="Alaska", duration=10)

In [9]: f.save()

In [10]: Flight.objects.all() 
Out[10]: <QuerySet [<Flight: Flight object (1)>, <Flight: Flight object (2)>, <Flight: Flight object (3)>, <Flight: Flight object (4)>]>

저의 경우 SQLite Browser에서 수행한 데이터베이스 작업을 저장하지 않았습니다.저장하면 문제가 해결됩니다.

매우 특이한 시나리오가 저에게 일어났습니다.

무한한 재귀가 있었고, 그것은 계속해서 물체를 만들었습니다.

좀 더 구체적으로 말하면, DRF를 사용하여 보기에서 작성 방법을 재정의하고 있었고, 그렇게 했습니다.

def create(self, request, *args, **kwargs):
    ....
    ....

    return self.create(request, *args, **kwargs)

이미 여기에 많은 답변이 있습니다. 제 사례를 공유하고 싶어도 누군가에게 도움이 될 수 있습니다.

Python API에서 값을 업데이트하기 위해 연결을 열었는데 서버 응답을 받은 후에만 연결을 닫겠습니다.여기서 제가 한 일은 Python API에서 연결을 닫기 전에 서버에서 다른 작업을 수행하기 위해 연결을 연 것입니다.

▁▁using우▁error를 사용하는 동안 이 오류가 하면,manage.py shell중이기 입니다.manage.py runserver데이터베이스를 잠그는 중입니다.셸을 사용하는 동안 서버를 중지하면 항상 문제가 해결됩니다.

실제로 "transaction.atomic() with select_for_update()"를 사용할 때 "Operational Error: database is locked"라는 오류 메시지가 표시되었습니다.

그리고 많은 시도/검색/읽은 django docs의 말처럼 select_for_update method를 지원하지 않는 SQLite 자체의 문제를 발견했습니다. 다음 URL을 보고 자세히 읽어보십시오.

https://docs.djangoproject.com/en/dev/ref/databases/ #filename-is-locked-messages

MySQL로 옮기자 모든 것이 잘 풀렸습니다.

django DOCs는 또한 데이터베이스 시간 초과가 발생할 때 "데이터베이스가 잠겨 있습니다"라고 말하기 때문에 다음 옵션을 설정하여 데이터베이스 시간 초과를 변경할 것을 권장합니다.

'OPTIONS': {
    # ...
    'timeout': 20,
    # ...
}

마지막으로, 저는 당신이 MySQL/Postgre를 사용하는 것을 추천합니다.개발 환경에서 작업하는 경우에도 SQL.

이것이 당신에게 도움이 되길 바랍니다.

에서 새 할때 이 가 발생했습니다. 하지만 SQLite는 SQLite입니다.session개체에 커밋되지 않은 변경 사항이 있습니다( 플러시됨).

다음 중 하나를 수행해야 합니다.

  1. 새 테이블을 만들기 전에 세션 커밋
  2. 모든 세션을 닫고 새 연결에서 테이블 만들기 수행
  3. ...

@Shilp Thapak의 대답은 맞습니다. 오류의 원인은 응용프로그램을 실행하기 전에 SQLite용 DB Browser에서 데이터에 대한 수동 변경사항을 작성하지 않았기 때문입니다.

사용 중인 SQL 클라이언트에서 변경사항을 작성하지 않은 경우에도 엔진을 생성할 수 있습니다.

engine.connect()

데이터베이스가 잠겨 있는 경우 작동 오류가 발생합니다.

롤백 저널이 있는지 확인하여 엔진이 연결될 수 있는지 확인할 수 있습니다.롤백 저널의 기본 모드는 트랜잭션의 시작과 끝에 생성 및 삭제됩니다.

데이터베이스가 있는 동일한 디렉토리에 존재하며, 데이터베이스 파일과 이름이 같고 접미사 "-journal"이 추가됩니다.

모드가 변경되지 않은 경우 SQLite용 DB Browser의 Edit pragmas 패널에 있는 필기장 모드.

다음과 같이 임시 파일이 있는지 확인할 수 있습니다.

if os.path.isfile('your-database.sqlite-journal'):
    print("The database is locked. Please write your changes in your SQL client before proceeding.\n")

임시 파일에 대한 자세한 내용은 여기를 참조하십시오.

따라서 SQLite용 서버나 DB Browser를 닫을 필요가 없습니다.실제로 모든 변경사항이 기록되는 한, 여러 클라이언트를 동시에 데이터베이스에 연결하고 응용프로그램을 동시에 실행할 수 있습니다.

저에게 그것은 단지 새 테이블을 만들기 위해 파이썬 코드를 실행하는 동시에 SQLite 앱의 데이터베이스에 액세스했기 때문입니다.코드가 완료될 때까지 SQLite를 닫으면 문제가 해결됩니다.

두 개 이상의 개발 편집기를 사용하여 해당 프로젝트에서 작업하는 경우 동일한 오류가 발생할 수 있습니다.

예를 들어 동일한 'prj.py ' 파일을 실행하는 스파이더 및 vscode는 레코드 삭제와 같은 일부 프로세스에서 충돌을 일으킵니다.

장고 버전 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 ... == ....

서버를 재부팅하기만 하면 데이터베이스가 잠겨 있는 현재 프로세스가 모두 지워집니다.

나는 단지 추가할 필요가 있었습니다.alias sqlite='sqlite3'나에게~/.zshrc

그런 다음 부분적으로 실패한 생성을 삭제했습니다.virtualenv~/.pyenv/versions/new-virtualenv안드레란pyenv virtualenv <name>그리고 그것은 순조롭게 작동했습니다.

다음 명령을 사용해 보십시오.

sudo fuser -k 8000/tcp

언급URL : https://stackoverflow.com/questions/3172929/operationalerror-database-is-locked

반응형