Permalink
Browse files

Enabled database-level autocommit for all backends.

This is mostly a documentation change.

It has the same backwards-incompatibility consequences as those
described for PostgreSQL in a previous commit.
  • Loading branch information...
1 parent cfc114e commit 5e27debc5cba30c84f99151a84c5fd846a65b091 @aaugustin aaugustin committed Mar 3, 2013
@@ -98,6 +98,8 @@ def connect(self):
conn_params = self.get_connection_params()
self.connection = self.get_new_connection(conn_params)
self.init_connection_state()
+ if not settings.TRANSACTIONS_MANAGED:
+ self.set_autocommit()
connection_created.send(sender=self.__class__, connection=self)
def ensure_connection(self):
@@ -136,7 +136,6 @@ def init_connection_state(self):
self.connection.cursor().execute(
self.ops.set_time_zone_sql(), [tz])
self.connection.set_isolation_level(self.isolation_level)
- self.set_autocommit(not settings.TRANSACTIONS_MANAGED)
def create_cursor(self):
cursor = self.connection.cursor()
@@ -69,7 +69,6 @@ even ``0``, because it doesn't make sense to maintain a connection that's
unlikely to be reused. This will help keep the number of simultaneous
connections to this database small.
-
The development server creates a new thread for each request it handles,
negating the effect of persistent connections.
@@ -104,7 +103,8 @@ Optimizing PostgreSQL's configuration
Django needs the following parameters for its database connections:
- ``client_encoding``: ``'UTF8'``,
-- ``default_transaction_isolation``: ``'read committed'``,
+- ``default_transaction_isolation``: ``'read committed'`` by default,
+ or the value set in the connection options (see below),
- ``timezone``: ``'UTC'`` when :setting:`USE_TZ` is ``True``, value of
:setting:`TIME_ZONE` otherwise.
@@ -118,30 +118,16 @@ will do some additional queries to set these parameters.
.. _ALTER ROLE: http://www.postgresql.org/docs/current/interactive/sql-alterrole.html
-Transaction handling
----------------------
-
-:doc:`By default </topics/db/transactions>`, Django runs with an open
-transaction which it commits automatically when any built-in, data-altering
-model function is called. The PostgreSQL backends normally operate the same as
-any other Django backend in this respect.
-
.. _postgresql-autocommit-mode:
Autocommit mode
-~~~~~~~~~~~~~~~
+---------------
-If your application is particularly read-heavy and doesn't make many
-database writes, the overhead of a constantly open transaction can
-sometimes be noticeable. For those situations, you can configure Django
-to use *"autocommit"* behavior for the connection, meaning that each database
-operation will normally be in its own transaction, rather than having
-the transaction extend over multiple operations. In this case, you can
-still manually start a transaction if you're doing something that
-requires consistency across multiple database operations. The
-autocommit behavior is enabled by setting the ``autocommit`` key in
-the :setting:`OPTIONS` part of your database configuration in
-:setting:`DATABASES`::
+.. versionchanged:: 1.6
+
+In previous versions of Django, database-level autocommit could be enabled by
+setting the ``autocommit`` key in the :setting:`OPTIONS` part of your database
+configuration in :setting:`DATABASES`::
DATABASES = {
# ...
@@ -150,29 +136,11 @@ the :setting:`OPTIONS` part of your database configuration in
},
}
-In this configuration, Django still ensures that :ref:`delete()
-<topics-db-queries-delete>` and :ref:`update() <topics-db-queries-update>`
-queries run inside a single transaction, so that either all the affected
-objects are changed or none of them are.
-
-.. admonition:: This is database-level autocommit
-
- This functionality is not the same as the :ref:`autocommit
- <topics-db-transactions-autocommit>` decorator. That decorator is
- a Django-level implementation that commits automatically after
- data changing operations. The feature enabled using the
- :setting:`OPTIONS` option provides autocommit behavior at the
- database adapter level. It commits after *every* operation.
-
-If you are using this feature and performing an operation akin to delete or
-updating that requires multiple operations, you are strongly recommended to
-wrap you operations in manual transaction handling to ensure data consistency.
-You should also audit your existing code for any instances of this behavior
-before enabling this feature. It's faster, but it provides less automatic
-protection for multi-call operations.
+Since Django 1.6, autocommit is turned on by default. This configuration is
+ignored and can be safely removed.
Isolation level
-~~~~~~~~~~~~~~~
+---------------
.. versionadded:: 1.6
@@ -200,7 +168,7 @@ such as ``REPEATABLE READ`` or ``SERIALIZABLE``, set it in the
.. _postgresql-isolation-levels: http://www.postgresql.org/docs/devel/static/transaction-iso.html
Indexes for ``varchar`` and ``text`` columns
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------------------------------------------
When specifying ``db_index=True`` on your model fields, Django typically
outputs a single ``CREATE INDEX`` statement. However, if the database type
@@ -457,7 +425,7 @@ Savepoints
Both the Django ORM and MySQL (when using the InnoDB :ref:`storage engine
<mysql-storage-engines>`) support database :ref:`savepoints
<topics-db-transactions-savepoints>`, but this feature wasn't available in
-Django until version 1.4 when such supports was added.
+Django until version 1.4 when such support was added.
If you use the MyISAM storage engine please be aware of the fact that you will
receive database-generated errors if you try to use the :ref:`savepoint-related
@@ -814,8 +814,8 @@ generating large CSV files.
.. admonition:: Performance considerations
Django is designed for short-lived requests. Streaming responses will tie
- a worker process and keep a database connection idle in transaction for
- the entire duration of the response. This may result in poor performance.
+ a worker process for the entire duration of the response. This may result
+ in poor performance.
Generally speaking, you should perform expensive tasks outside of the
request-response cycle, rather than resorting to a streamed response.
View
@@ -30,6 +30,18 @@ prevention <clickjacking-prevention>` are turned on.
If the default templates don't suit your tastes, you can use :ref:`custom
project and app templates <custom-app-and-project-templates>`.
+Improved transaction management
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Django's transaction management was overhauled. Database-level autocommit is
+now turned on by default. This makes transaction handling more explicit and
+should improve performance. The existing APIs were deprecated, and new APIs
+were introduced, as described in :doc:`/topics/db/transactions`.
+
+Please review carefully the list of :ref:`known backwards-incompatibilities
+<transactions-changes-from-1.5>` to determine if you need to make changes in
+your code.
+
Persistent database connections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -148,6 +160,16 @@ Backwards incompatible changes in 1.6
deprecation timeline for a given feature, its removal may appear as a
backwards incompatible change.
+* Database-level autocommit is enabled by default in Django 1.6. While this
+ doesn't change the general spirit of Django's transaction management, there
+ are a few known backwards-incompatibities, described in the :ref:`transaction
+ management docs <transactions-changes-from-1.5>`. You should review your code
+ to determine if you're affected.
+
+* In previous versions, database-level autocommit was only an option for
+ PostgreSQL, and it was disabled by default. This option is now
+ :ref:`ignored <postgresql-autocommit-mode>`.
+
* The ``django.db.models.query.EmptyQuerySet`` can't be instantiated any more -
it is only usable as a marker class for checking if
:meth:`~django.db.models.query.QuerySet.none` has been called:
@@ -201,31 +201,32 @@ perform queries that don't map cleanly to models, or directly execute
In these cases, you can always access the database directly, routing around
the model layer entirely.
-The object ``django.db.connection`` represents the
-default database connection, and ``django.db.transaction`` represents the
-default database transaction. To use the database connection, call
-``connection.cursor()`` to get a cursor object. Then, call
-``cursor.execute(sql, [params])`` to execute the SQL and ``cursor.fetchone()``
-or ``cursor.fetchall()`` to return the resulting rows. After performing a data
-changing operation, you should then call
-``transaction.commit_unless_managed()`` to ensure your changes are committed
-to the database. If your query is purely a data retrieval operation, no commit
-is required. For example::
+The object ``django.db.connection`` represents the default database
+connection. To use the database connection, call ``connection.cursor()`` to
+get a cursor object. Then, call ``cursor.execute(sql, [params])`` to execute
+the SQL and ``cursor.fetchone()`` or ``cursor.fetchall()`` to return the
+resulting rows.
+
+For example::
+
+ from django.db import connection
def my_custom_sql():
- from django.db import connection, transaction
cursor = connection.cursor()
- # Data modifying operation - commit required
cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
- transaction.commit_unless_managed()
- # Data retrieval operation - no commit required
cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
row = cursor.fetchone()
return row
+.. versionchanged:: 1.6
+ In Django 1.5 and earlier, after performing a data changing operation, you
+ had to call ``transaction.commit_unless_managed()`` to ensure your changes
+ were committed to the database. Since Django now defaults to database-level
+ autocommit, this isn't necessary any longer.
+
If you are using :doc:`more than one database </topics/db/multi-db>`, you can
use ``django.db.connections`` to obtain the connection (and cursor) for a
specific database. ``django.db.connections`` is a dictionary-like
@@ -235,7 +236,6 @@ alias::
from django.db import connections
cursor = connections['my_db_alias'].cursor()
# Your code here...
- transaction.commit_unless_managed(using='my_db_alias')
By default, the Python DB API will return results without their field
names, which means you end up with a ``list`` of values, rather than a
@@ -260,27 +260,18 @@ Here is an example of the difference between the two::
>>> dictfetchall(cursor)
[{'parent_id': None, 'id': 54360982L}, {'parent_id': None, 'id': 54360880L}]
-
-.. _transactions-and-raw-sql:
-
-Transactions and raw SQL
-------------------------
-
-When you make a raw SQL call, Django will automatically mark the
-current transaction as dirty. You must then ensure that the
-transaction containing those calls is closed correctly. See :ref:`the
-notes on the requirements of Django's transaction handling
-<topics-db-transactions-requirements>` for more details.
-
Connections and cursors
-----------------------
``connection`` and ``cursor`` mostly implement the standard Python DB-API
-described in :pep:`249` (except when it comes to :doc:`transaction handling
-</topics/db/transactions>`). If you're not familiar with the Python DB-API, note
-that the SQL statement in ``cursor.execute()`` uses placeholders, ``"%s"``,
-rather than adding parameters directly within the SQL. If you use this
-technique, the underlying database library will automatically add quotes and
-escaping to your parameter(s) as necessary. (Also note that Django expects the
-``"%s"`` placeholder, *not* the ``"?"`` placeholder, which is used by the SQLite
-Python bindings. This is for the sake of consistency and sanity.)
+described in :pep:`249` — except when it comes to :doc:`transaction handling
+</topics/db/transactions>`.
+
+If you're not familiar with the Python DB-API, note that the SQL statement in
+``cursor.execute()`` uses placeholders, ``"%s"``, rather than adding
+parameters directly within the SQL. If you use this technique, the underlying
+database library will automatically escape your parameters as necessary.
+
+Also note that Django expects the ``"%s"`` placeholder, *not* the ``"?"``
+placeholder, which is used by the SQLite Python bindings. This is for the sake
+of consistency and sanity.
Oops, something went wrong.

0 comments on commit 5e27deb

Please sign in to comment.