Dear Django group,
please consider this code:
from datetime import date
from django.db import models
class TestModel(models.Model):
jahr = models.SmallIntegerField()
monat = models.SmallIntegerField()
some_value = models.SmallIntegerField()
class Meta:
unique_together = ('jahr', 'monat')
def demonstrate_the_problem():
d = date.today()
try:
t = TestModel.objects.get(jahr=d.year, monat=d.month)
# t exists, no need to create or modify it.
return t.some_value
except TestModel.DoesNotExist:
# t did not yet exist, so we have to create it anew.
# Note that there is a "unique together" constraint in place
# that makes sure that the tuple (jahr, monat) only exists once.
# Thus we create a new instance, then lock it with
# select_for_update() -- but this is still not atomic!
TestModel(jahr=d.year, monat=d.month).save()
t = TestModel.objects.get(
jahr=d.year, monat=d.month).select_for_update()
# A long computation, eventually setting fields in the new t,
# then saving it for the next call to this function.
t.some_value = 123
t.save()
return t.some_value
The problem is that another thread too may have created a TestModel with the
same (jahr, monat) in the timespan between our "does not exist" and "lock",
triggering a violation of the "unique" constraint.
Thus, the question is how we can make the sequence "does not exist – create anew
– lock" atomic?
Any feedback would very much be appreciated!
Many thanks and best regards,
Carsten
--
You received this message because you are subscribed to the Google Groups "Django
users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-users/5733370C.2050001%40cafu.de.
For more options, visit https://groups.google.com/d/optout.