2017-09-14 5 views
0

assets django app는 SQLite에서 잘 실행되지만 레코드의 큰 세트를 삭제하거나 업데이트 할 때 성능 문제가 있습니다. PostgreSQL 데이터베이스.django django DoesNotExist 일치하는 쿼리가 포스트그레스에만 존재하지 않습니다.

이렇게하려면 신선한 데이터베이스로 시작하여 assets/migrations/ 디렉토리를 삭제하고 theapp/settings.py을 업데이트하여 PostgreSQL을 구성해야합니다. 그때 실행하고 있습니다 :

./manage.py makemigrations assets 
./manage.py migrate --run-syncdb 
./manage.py createsuperuser 

내가 등록 post_create 신호 내에서 호출하는 기능이있다. Scan 개체가 만들어 질 때 검사를 실행합니다.

@classmethod 
def post_create(cls, sender, instance, created, *args, **kwargs): 
    if not created: 
     return 

    from celery.result import AsyncResult 
    # get the domains for the project, from scan 
    print("debug: task = tasks.populate_endpoints.delay({})".format(instance.pk)) 
    task = tasks.populate_endpoints.delay(instance.pk) 

기분을 상하게하는 코드 : 제기

from celery import shared_task 
.... 
import datetime 

@shared_task 
def populate_endpoints(scan_pk): 
    from .models import Scan, Project, 
    from anotherapp.plugins.sensual import subdomains 

    scan = Scan.objects.get(pk=scan_pk) #<<<<<<<< django no like 
    new_entries_count = 0 
    project = Project.objects.get(id=scan.project.id) 
    .... 

결과의 예외 DoesNotExist :

debug: task = tasks.populate_endpoints.delay(2) 
    [2017-09-14 23:18:34,950: ERROR/ForkPoolWorker-8] Task assets.tasks.populate_endpoints[4555d329-2873-4184-be60-55e44c46a858] raised unexpected: DoesNotExist('Scan matching query does not exist.',) 
    Traceback (most recent call last): 
     File "/usr/local/lib/python3.6/site-packages/celery/app/trace.py", line 374, in trace_task 
     R = retval = fun(*args, **kwargs) 
     File "/usr/local/lib/python3.6/site-packages/celery/app/trace.py", line 629, in __protected_call__ 
     return self.run(*args, **kwargs) 
    File "/usr/src/app/theapp/assets/tasks.py", line 12, in populate_endpoints 
    scan = Scan.objects.get(pk=scan_pk) 

./manage.py shell을 통해 상호 작용 그러나 PK의 ==와 Scan 객체 2의 존재를 나타내는 클래스 assets.models.Scan 내 :

>>> from assets.models import Scan 
>>> Scan.objects.all() 
<QuerySet [<Scan: ACME Web Test Scan>]> 
>>> s = Scan.objects.all().first() 
>>> s.pk 
2 

내 생각에 post_create 함수가 호출 될 때 save()이 호출되었지만 Scan 개체는 여전히 PostgreSQL 데이터베이스에 존재하지 않습니다.
SQLite는이 문제를 나타내지 않습니다.
DoesNotExist 예외는 상당히 일반적인 것으로 보이고 여러 가지로 인해 발생하므로 stackoverflow 관련 문제를 발견하지 못했습니다. 이것에 대한 아이디어는 많이 감사하겠습니다.

+0

두 가지 pks가 같은 유형입니까? 모델 사양을 제공하지 않았습니다. 명시 적으로 선언하지 않으면 int이어야합니다. 하지만 한 데이터베이스에서 다른 데이터베이스로 마이그레이션 할 때 이것이 문제가 될 수 있는지 여부는 확실하지 않습니다. – Risadinha

답변

1

트랜잭션 및 격리 수준으로 인해 well known problem이 발생합니다. 트랜잭션이 실행될 때 트랜잭션이 커밋되지 않고 격리 수준이 READ COMMITED 인 경우 실제로 다른 프로세스에서이 레코드를 읽을 수 없습니다. 용액으로서 Django 1.9 introduced the on_commit hook.

NB : 기술적으로이 질문은 Django related objects are missing from celery task (race condition?)의 복제본이지만 받아 들인 대답은 django-transaction-hooks을 사용하며 이후 django에 병합되었습니다.

+0

감사 브루노, 나는 첫 번째 링크에서'TransactionAwareTask' 클래스 스 니펫을 성공적으로 수정했습니다. – user1330734

관련 문제