select_for_update(nowait=False)
Returns a queryset that will lock rows until the end of the transaction, generating a SELECT ... FOR UPDATE
SQL statement on supported databases.
For example:
entries = Entry.objects.select_for_update().filter(author=request.user)
All matched entries will be locked until the end of the transaction block, meaning that other transactions will be prevented from changing or acquiring locks on them.
Usually, if another transaction has already acquired a lock on one of the selected rows, the query will block until the lock is released. If this is not the behavior you want, call select_for_update(nowait=True)
. This will make the call non-blocking. If a conflicting lock is already acquired by another transaction, DatabaseError
will be raised when the queryset is evaluated.
Currently, the postgresql
, oracle
, and mysql
database backends support select_for_update()
. However, MySQL has no support for the nowait
argument. Obviously, users of external third-party backends should check with their backend’s documentation for specifics in those cases.
Passing nowait=True
to select_for_update()
using database backends that do not support nowait
, such as MySQL, will cause a DatabaseError
to be raised. This is in order to prevent code unexpectedly blocking.
Evaluating a queryset with select_for_update()
in autocommit mode on backends which support SELECT ... FOR UPDATE
is a TransactionManagementError
error because the rows are not locked in that case. If allowed, this would facilitate data corruption and could easily be caused by calling code that expects to be run in a transaction outside of one.
Using select_for_update()
on backends which do not support SELECT ... FOR UPDATE
(such as SQLite) will have no effect. SELECT ... FOR UPDATE
will not be added to the query, and an error isn’t raised if select_for_update()
is used in autocommit mode.
Warning
Although select_for_update()
normally fails in autocommit mode, since TestCase
automatically wraps each test in a transaction, calling select_for_update()
in a TestCase
even outside an atomic()
block will (perhaps unexpectedly) pass without raising a TransactionManagementError
. To properly test select_for_update()
you should use TransactionTestCase
.
Please login to continue.