Django: How to acquire a lock on the database rows?
select_for_update
is the answer if you want to acquire a lock on the row. The lock is only released after the transaction is completed. This is similar to the Select for update statement
in the SQL query.
>>> Dealership.objects.select_for_update().get(pk='iamid')
>>> # Here lock is only required on Dealership object
>>> Dealership.objects.select_related('oem').select_for_update(of=('self',))
select_for_update
have these four arguments with these default value
– nowait=False
– skiplocked=False
– of=()
– nokey=False
Let's see what these all arguments mean
nowait
Think of the scenario where the lock is already acquired by another query, in this case, you want your query to wait or raise an error, This behavior can be controlled by nowait
, If nowait=True
we will raise the DatabaseError
otherwise it will wait for the lock to be released.
skip_locked
As somewhat name implies, it helps to decide whether to consider a locked row in the evaluated query. If the skip_locked=true
locked rows will not be considered.
nowait and skip_locked are mutually exclusive using both together will raise ValueError
of
In select_for_update
when the query is evaluated, the lock is also acquired on the select related rows as in the query. If one doesn't wish the same, they can use of
where they can specify fields to acquire a lock on
>>> Dealership.objects.select_related('oem').select_for_update(of=('self',))
# Just be sure we don't have any nullable relation with OEM
no_key
This helps you to create a weak lock. This means the other query can create new rows which refer to the locked rows (any reference relationship).
Few more important points to keep in mind select_for_update
doesn't allow nullable relations, you have to explicitly exclude these nullable conditions. In auto-commit mode, select_for_update
fails with error TransactionManagementError
you have to add code in a transaction explicitly. I have struggled around these points :).
Here is all about select_for_update
which you require to know to use in your code and to do changes to your database.
Cheers!