projektzapisy icon indicating copy to clipboard operation
projektzapisy copied to clipboard

IntegrityError: duplicate key value violates unique constraint "records_t0times_student_id_semester_id_8a0806b6_uniq" DETAIL: Key (student_id, semester_id)=(2873, 346) already exists.

Open rollbar[bot] opened this issue 3 years ago • 1 comments

View details in Rollbar: https://rollbar.com/iiuni/projektzapisy/items/491/

Traceback (most recent call last):
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/newrelic/hooks/framework_django.py", line 554, in wrapper
    return wrapped(*args, **kwargs)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 614, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/contrib/admin/sites.py", line 233, in inner
    return view(request, *args, **kwargs)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1719, in changelist_view
    response = self.response_action(request, queryset=cl.get_queryset(request))
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1402, in response_action
    response = func(self, request, queryset)
  File "/home/zapisy/deploy/releases/20220913111411/zapisy/apps/enrollment/courses/admin.py", line 63, in refresh_opening_times
    T0Times.populate_t0(semester)
  File "/usr/lib/python3.8/contextlib.py", line 75, in inner
    return func(*args, **kwds)
  File "/home/zapisy/deploy/releases/20220913111411/zapisy/apps/enrollment/records/models/opening_times.py", line 111, in populate_t0
    cls.objects.bulk_create(created)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/db/models/query.py", line 506, in bulk_create
    returned_columns = self._batched_insert(
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/db/models/query.py", line 1271, in _batched_insert
    inserted_rows.extend(self._insert(
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/db/models/query.py", line 1254, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1397, in execute_sql
    cursor.execute(sql, params)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/newrelic/hooks/database_psycopg2.py", line 64, in execute
    return super(CursorWrapper, self).execute(sql, parameters, *args,
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/newrelic/hooks/database_dbapi2.py", line 38, in execute
    return self.__wrapped__.execute(sql, parameters,
IntegrityError: duplicate key value violates unique constraint "records_t0times_student_id_semester_id_8a0806b6_uniq"
DETAIL:  Key (student_id, semester_id)=(2873, 346) already exists.
Traceback (most recent call last):
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/newrelic/hooks/database_psycopg2.py", line 64, in execute
    return super(CursorWrapper, self).execute(sql, parameters, *args,
  File "/home/zapisy/deploy/releases/20220913111411/venv/lib/python3.8/site-packages/newrelic/hooks/database_dbapi2.py", line 38, in execute
    return self.__wrapped__.execute(sql, parameters,
UniqueViolation: duplicate key value violates unique constraint "records_t0times_student_id_semester_id_8a0806b6_uniq"
DETAIL:  Key (student_id, semester_id)=(2873, 346) already exists.

rollbar[bot] avatar Sep 16 '22 11:09 rollbar[bot]

Błąd można zreplikować uruchamiając równolegle obliczenia czasów otwarcia zapisów dla danego semestru w panelu administratora. Problem bierze się z wyścigów między powstałymi w ten sposób transakcjami. Atrakcyjnym rozwiązaniem byłoby ustawienie poziomu izolacji "serializable" dla tych transakcji i złapanie wyrzuconego wyjątku. Niestety, Django zdaje się nie oferować zbyt dobrego wsparcia dla takiego podejścia (tj. nie mamy jawnego sposobu ustawiania poziomów izolacji dla indywidualnych transakcji, ale istnieją rozszerzenia, które twierdzą, że to potrafią) . Być może warto rozważyć dodanie osobnego połączenia z bazą danych w pliku settings.py o odpowiednim poziomie izolacji. Takie połączenie mogłoby wówczas być wykorzystywane przez wybrane transakcje (np. poprzez dekorator @transaction.atomic(using='<nazwa połączenia>')). Do alternatywnych (lecz raczej nieskutecznych) podejść należy definiowanie własnych kursorów lub dedykowany nowemu połączeniu manager. Pozostaje też problem złapania wyjątku, jako że kod odpowiadający za przebieg transakcji traci sterowanie w momencie naruszenia zasad wymuszonych przez wybrany poziom izolacji.

ventus550 avatar Dec 16 '22 10:12 ventus550