Made atomic usable when autocommit is off.

Thanks Anssi for haggling until I implemented this.

This change alleviates the need for atomic_if_autocommit. When
autocommit is disabled for a database, atomic will simply create and
release savepoints, and not commit anything. This honors the contract of
not doing any transaction management.

This change also makes the hack to allow using atomic within the legacy
transaction management redundant.

None of the above will work with SQLite, because of a flaw in the design
of the sqlite3 library. This is a known limitation that cannot be lifted
without unacceptable side effects eg. triggering arbitrary commits.
This commit is contained in:
Aymeric Augustin 2013-03-13 14:08:32 +01:00
parent bd0cba58aa
commit 83a416f5e7
5 changed files with 106 additions and 114 deletions

View file

@ -153,9 +153,6 @@ Django provides a single API to control database transactions.
to commit, roll back, or change the autocommit state of the database
connection within an ``atomic`` block will raise an exception.
``atomic`` can only be used in autocommit mode. It will raise an exception
if autocommit is turned off.
Under the hood, Django's transaction management code:
- opens a transaction when entering the outermost ``atomic`` block;
@ -171,6 +168,10 @@ Django provides a single API to control database transactions.
the overhead of savepoints is noticeable. It has the drawback of breaking
the error handling described above.
You may use ``atomic`` when autocommit is turned off. It will only use
savepoints, even for the outermost block, and it will raise an exception
if the outermost block is declared with ``savepoint=False``.
.. admonition:: Performance considerations
Open transactions have a performance cost for your database server. To
@ -271,9 +272,8 @@ another. Review the documentation of the adapter you're using carefully.
You must ensure that no transaction is active, usually by issuing a
:func:`commit` or a :func:`rollback`, before turning autocommit back on.
:func:`atomic` requires autocommit to be turned on; it will raise an exception
if autocommit is off. Django will also refuse to turn autocommit off when an
:func:`atomic` block is active, because that would break atomicity.
Django will refuse to turn autocommit off when an :func:`atomic` block is
active, because that would break atomicity.
Transactions
------------
@ -392,8 +392,11 @@ When autocommit is enabled, savepoints don't make sense. When it's disabled,
commits before any statement other than ``SELECT``, ``INSERT``, ``UPDATE``,
``DELETE`` and ``REPLACE``.)
As a consequence, savepoints are only usable inside a transaction ie. inside
an :func:`atomic` block.
This has two consequences:
- The low level APIs for savepoints are only usable inside a transaction ie.
inside an :func:`atomic` block.
- It's impossible to use :func:`atomic` when autocommit is turned off.
Transactions in MySQL
---------------------
@ -584,9 +587,6 @@ During the deprecation period, it's possible to use :func:`atomic` within
However, the reverse is forbidden, because nesting the old decorators /
context managers breaks atomicity.
If you enter :func:`atomic` while you're in managed mode, it will trigger a
commit to start from a clean slate.
Managing autocommit
~~~~~~~~~~~~~~~~~~~
@ -623,8 +623,8 @@ Disabling transaction management
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Instead of setting ``TRANSACTIONS_MANAGED = True``, set the ``AUTOCOMMIT`` key
to ``False`` in the configuration of each database, as explained in :ref
:`deactivate-transaction-management`.
to ``False`` in the configuration of each database, as explained in
:ref:`deactivate-transaction-management`.
Backwards incompatibilities
---------------------------