[Issue] - APScheduler "database is locked"

KimJiHong·2023년 12월 1일
0

Issue

목록 보기
7/7

Issue

나는 APScheduler로 1시간마다 블랙리스트에 등록된 JWT중 기간이 만료된 토큰을 삭제하는 작업을 구현했다.

# sheduler.py
@transaction.atomic
def clean_expiry_token():
    now_date = timezone.now()
    expired_tokens = OutstandingToken.objects.filter(expires_at__lt= now_date)
    print(f"기간 지난 refresh 토큰 수 => {len(expired_tokens)}")

    if expired_tokens != 0:
        for instance in expired_tokens:
            token_id = instance.id
            try:
                blacklist_instance= BlacklistedToken.objects.get(id= token_id)
                blacklist_instance.delete()

            except:
            	pass

            instance.delete()

그런데 Scheduler가 몇번은 문제없이 JOB이 실행되는데, 또 몇번은 "database is locked" 오류와 함께 정상적으로 실행되지 않고 있다.

안될꺼면 전부다 안되야지.. 어떤 경우엔 되고 어떤 경우에 안되고 하는지 확실히 모르겠다.

Issue in Django Docs.

나는 database is locked 에 관한 문제를 Django 공식 문서에서 확인할 수 있었다.

내용을 요약해보면 다음과 같다.

장고의 기본 데이터베이스인 SQLite3는 경량 데이터베이스로 고수준의 Multi-thread를 지원할 수 없어 동시에 데이터베이스에 작업을 할 때, "database is lock" 오류가 발생한다.

즉, SQLite3의 한계로 인한 오류이다.

Django 공식 문서에서 제시하는 해결 방안은

Solution.1 - 경량 DB인 SQLite3 말고 다른 DB 사용하기.
Solution.2 - 동시성과 트랜젝션 줄이는 코드로 다시 작성.
Solution.3 - 기본 Timeout 시간을 늘리기.

Solution

나는 "database is locked" 문제를 근본적으로 해결하기 위해서는

경량 DB인 SQLite3 말고 고수준의 동시성을 지원하는 MySQL이나 PostgreSQL을 사용하는게 좋을 것 같다는 생각이 들었다.

그래서, 데이터베이스를 PostgreSQL로 변경하고 오류를 해결했다.

데이터베이스 자체를 바꾸고 난 뒤, 정상적으로 작동하고 있다!


Set Default Database: PostgreSQL

  1. Django에서 PostgreSQL을 사용하기 위해 psycopg2 라이브러리 설치
$ pip install pycopg2
  1. PostgreSQL Shell: 새로운 DataBase 생성
$ psql postgres

# 새로운 DB(pg_db) 생성
postgres=# create database pg_db;
# pg_db 와 연결
postgres=# \connect pg_db;
# 사용자 root_kim 생성 및 root_kim 비밀번호 password
project=# create user root_kim with password 'password';
# utf-8 인코딩
project=# alter role root_kim set client_encoding to 'utf-8';
# 시간대 설정
project=# alter role root_kim set timezone to 'Asia/Seoul';
# root_kim 권한 부여
project=# grant all privileges on database pg_db to root_kim;

  1. Django와 PostgreSQL 연결
# settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'pg_db', 
        'USER': 'root_kim',
        'PASSWORD': 'password',
        'HOST': '127.0.0.1', # default
        'PORT': '5432', # default
    }
}

Ref.

https://docs.djangoproject.com/en/dev/ref/databases/#database-is-locked-errors
https://velog.io/@chaeri93/Django-Django와-Postgresql-연동하기

profile
https://h0ng.dev

0개의 댓글

관련 채용 정보