Django select_for_update

select_for_update queryset’de donen rowlar uzerinde ayni anda birden fazla update/delete querysi calismasini engeller.

Asagidaki kodu inceledigimizde ayni anda ayni bayi(Dealer)‘in bakiyesi guncellenmesini engelliyoruz. Bu acilan DB transactioni bitene kadar ikinci request Dealer‘in cekildigi satirda bekler.

@transaction.atomic
def post(self, request, **kwargs):
    d = Dealer.objects.select_for_update().get(pk=self.kwargs['pk'])
    d.balance -= 100
    d.save()
    ...

select_for_update kullanmadigimiz durumda ayni anda ayni bayi icin bu query calistiginda(bayinin bakiyesinin 1000 oldugunu varsayarsak) ayni anda calistiklari icin islem sonucunda bakiye 800 kalmasi gerekirken 900 kalacaktir.

Bu sebeple update/delete querylerinin calistigi yerlerde transaction’i acar acmaz ilk isimiz update edilecek objeleri select_for_update ile cekmek olmalidir.

Not: Django querysetler lazy oldugu icin query’nin yazildigi satirda degil cekildigi satira gelince obur calisan queryi beklemeye baslayacagini unutmamak lazim.

Not2: select_for_update eklenmedigi icin olusan hatalari bulmak zordur.

Load comments