DBMS’ ACID (Atomicity, Consistency, Isolation, Durability) and transaction
in Django.
update
Within One Step
If we need to update only one field of a model (That is, no other field or model need to be updated simultaneously to ensure the consistency of ACID), we can use F()
, select_for_update()
and filter()
to update field without race condition..
Following example:
- Check if the product adequate for
n
quantity before selling.- If adequate, sell
n
products. - If inadequate, sell nothing.
- If adequate, sell
1 | from django.db.models import F |
select_for_update()
returns a queryset that will lock rows until the end of the transaction (generatingSELECT ... FOR UPDATE
)FIELDNAME__gte = number
means greater than or equal tonumber
.filter()
always return an objects set.
When no object satisfied the query’s condition (quantity >= n
), returns an empty set.
An empty set won’t trigger theupdate()
manipulation.get()
always return one object. Raise error when get more than one.filter()
always return an objects set.(obj, obj, obj, ...)
F()
object represents the value of a model field. It makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory.
Transaction With Multiple Steps
But we still need transaction with multiple steps. So use django.db.transaction.atomic()
to ensure ACID’s atomic.
A transaction usually need to update multiple fields across models, so we implement the mechanism in
views.py
instead ofmodels.py
.
Now the following example implement the mechanism of add_to_cart()
:
- User requests for
n
amount products via a form.- If quantity > requested amount
n
:- sell
n
products; - add
n
items into myCart
model.
- sell
- If (quantity < requested amount
n
) && (quantity > 0):- sell out all stock of the quantity;
- add sold items into my
Cart
model.
- Else:
- Sell nothing.
- If quantity > requested amount
1 | from django.db import transaction |