(06.18) 수정됨.
에러 내용
Traceback (most recent call last):
File "C:\CODE\PYTHON\DJANGO\venv-django\Lib\site-packages\django\db\models\query.py", line 948, in get_or_create
return self.get(**kwargs), False
^^^^^^^^^^^^^^^^^^
File "C:\CODE\PYTHON\DJANGO\venv-django\Lib\site-packages\django\db\models\query.py", line 649, in get
raise self.model.DoesNotExist(
{model}.DoesNotExist: {model} matching query does not exist.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\CODE\PYTHON\DJANGO\venv-django\Lib\site-packages\django\db\backends\utils.py", line 105, in _execute
return self.cursor.execute(sql, params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\CODE\PYTHON\DJANGO\venv-django\Lib\site-packages\django\db\backends\sqlite3\base.py", line 354, in execute
return super().execute(query, params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sqlite3.OperationalError: database is locked
해결 방법
db를 sqlite가 아닌 psql 같이 동시성 작업을 지원하는 db로 바꾼다.
또는 트랜잭션을 이용한다.
설명
설명
sqlite에는 1가지 문제가 있는데, 동시 사용이 안된다는 것이다.
무슨 말이냐면, 만약 누군가가 sqlite 파일을 편집 중이라면, 그 편집이 끝나기 전까지 다른 사람이 파일을 편집할 수 없다.
만약 편집 중인 sqlite 파일을 다른 사람이 편집을 시도하면 발생하는게 바로 "sqlite3.OperationalError: database is locked" 에러다.
내 경우에는 4개의 모델을 연속으로 get_or_create하는 것이 문제였다.
모든 객체가 존재해서 get이 연속으로 사용될 때는 문제가 없지만, 그렇지 않아 create가 연속으로 이루어질 때가 문제였다.
db를 sqlite에서 다른 것으로 변경할 예정은 아직 잇지 않았기 때문에 트랜잭션을 이용해서 문제를 해결했다.
예시는 다음과 같다.
from django.db import transaction
with transaction.atomic():
obj1, created1 = Model1.objects.get_or_create(...)
obj2, created2 = Model2.objects.get_or_create(...)
obj3, created3 = Model3.objects.get_or_create(...)
transaction.atomic()의 역할
장고는 기본적으로 하나의 작업을 하면 자동으로 commit, 즉 데이터베이스에 쓰기 작업을 한다.
with transaction.atomic()문을 실행하면 auto commit이 일시적으로 중단되며, with문이 끝났을 때 db에 기록을 시작하게 한다고 한다.
자세한 내용은 장고의 Database transactions 문서에서 확인해보자.