]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- add more dragons to session.begin() / autocommit docs
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 28 Sep 2017 15:43:48 +0000 (11:43 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 28 Sep 2017 15:44:09 +0000 (11:44 -0400)
Change-Id: I9e326f353d396321565dfbf53b7a30f18d8c86e9
(cherry picked from commit 1ec7ba52e1c7e6d232223912f154e25252fb9b92)

doc/build/orm/session_transaction.rst
lib/sqlalchemy/orm/session.py

index 955ec02f6e6cf6be48a0afeb52467b8a66aa1a0a..bd06286a6e11bb77a262b2b7ff4a787789910c66 100644 (file)
@@ -81,7 +81,7 @@ The example below illustrates this lifecycle::
         # state.  Neither of these steps are usually essential.
         # However, if the commit() or rollback() itself experienced
         # an unanticipated internal failure (such as due to a mis-behaved
-        # user-defined event handler), .close() will ensure that 
+        # user-defined event handler), .close() will ensure that
         # invalid state is removed.
         session.close()
 
@@ -141,39 +141,45 @@ things like unique constraint exceptions::
 Autocommit Mode
 ---------------
 
-The example of :class:`.Session` transaction lifecycle illustrated at
-the start of :ref:`unitofwork_transaction` applies to a :class:`.Session` configured in the
-default mode of ``autocommit=False``.   Constructing a :class:`.Session`
-with ``autocommit=True`` produces a :class:`.Session` placed into "autocommit" mode, where each SQL statement
-invoked by a :meth:`.Session.query` or :meth:`.Session.execute` occurs
-using a new connection from the connection pool, discarding it after
-results have been iterated.   The :meth:`.Session.flush` operation
-still occurs within the scope of a single transaction, though this transaction
-is closed out after the :meth:`.Session.flush` operation completes.
+The examples of session lifecycle at :ref:`unitofwork_transaction` refer
+to a :class:`.Session` that runs in its default mode of ``autocommit=False``.
+In this mode, the :class:`.Session` begins new transactions automatically
+as soon as it needs to do work upon a database connection; the transaction
+then stays in progress until the :meth:`.Session.commit` or :meth:`.Session.rollback`
+methods are called.
+
+The :class:`.Session` also features an older legacy mode of use called
+**autocommit mode**, where a transaction is not started implicitly, and unless
+the the :meth:`.Session.begin` method is invoked, the :class:`.Session` will
+perform each database operation on a new connection checked out from the
+connection pool, which is then released back to the pool immediately
+after the operation completes.  This refers to
+methods like :meth:`.Session.execute` as well as when executing a query
+returned by :meth:`.Session.query`.  For a flush operation, the :class:`.Session`
+starts a new transaction for the duration of the flush, and commits it when
+complete.
 
 .. warning::
 
-    "autocommit" mode should **not be considered for general use**.
-    If used, it should always be combined with the usage of
-    :meth:`.Session.begin` and :meth:`.Session.commit`, to ensure
-    a transaction demarcation.
-
-    Executing queries outside of a demarcated transaction is a legacy mode
-    of usage, and can in some cases lead to concurrent connection
-    checkouts.
-
-    In the absence of a demarcated transaction, the :class:`.Session`
-    cannot make appropriate decisions as to when autoflush should
-    occur nor when auto-expiration should occur, so these features
-    should be disabled with ``autoflush=False, expire_on_commit=False``.
-
-Modern usage of "autocommit" is for framework integrations that need to control
-specifically when the "begin" state occurs.  A session which is configured with
-``autocommit=True`` may be placed into the "begin" state using the
-:meth:`.Session.begin` method.
-After the cycle completes upon :meth:`.Session.commit` or :meth:`.Session.rollback`,
-connection and transaction resources are :term:`released` and the :class:`.Session`
-goes back into "autocommit" mode, until :meth:`.Session.begin` is called again::
+    "autocommit" mode is a **legacy mode of use** and should not be
+    considered for new projects.   If autocommit mode is used, it is strongly
+    advised that the application at least ensure that tranasction scope
+    is made present via the :meth:`.Session.begin` method, rather than
+    using the session in pure autocommit mode.
+
+    If the :meth:`.Session.begin` method is not used, and operations are allowed
+    to proceed using ad-hoc connections with immediate autocommit, then the
+    application probably should set ``autoflush=False, expire_on_commit=False``,
+    since these features are intended to be used only within the context
+    of a database transaction.
+
+Modern usage of "autocommit mode" tends to be for framework integrations that
+wish to control specifically when the "begin" state occurs.  A session which is
+configured with ``autocommit=True`` may be placed into the "begin" state using
+the :meth:`.Session.begin` method. After the cycle completes upon
+:meth:`.Session.commit` or :meth:`.Session.rollback`, connection and
+transaction resources are :term:`released` and the :class:`.Session` goes back
+into "autocommit" mode, until :meth:`.Session.begin` is called again::
 
     Session = sessionmaker(bind=engine, autocommit=True)
     session = Session()
@@ -189,7 +195,7 @@ goes back into "autocommit" mode, until :meth:`.Session.begin` is called again::
         raise
 
 The :meth:`.Session.begin` method also returns a transactional token which is
-compatible with the Python 2.6 ``with`` statement::
+compatible with the ``with`` statement::
 
     Session = sessionmaker(bind=engine, autocommit=True)
     session = Session()
index 2c040561b09b0dee3b8cd9edda5de6db6edb9a21..b79c435dd905a8159e0c097ee212a0b4bde159cd 100644 (file)
@@ -778,20 +778,35 @@ class Session(_SessionClassMethods):
     def begin(self, subtransactions=False, nested=False):
         """Begin a transaction on this :class:`.Session`.
 
-        The :meth:`.Session.begin` method is only
-        meaningful if this session is in **autocommit mode** prior to
-        it being called; see :ref:`session_autocommit` for background
-        on this setting.
+        .. warning::
 
-        The method will raise an error if this :class:`.Session`
-        is already inside of a transaction, unless
-        :paramref:`.Session.begin.subtransactions` or
-        :paramref:`.Session.begin.nested` are specified.
+            The :meth:`.Session.begin` method is part of a larger pattern
+            of use with the :class:`.Session` known as **autocommit mode**.
+            This is essentially a **legacy mode of use** and is
+            not necessary for new applications.    The :class:`.Session`
+            normally handles the work of "begin" transparently, which in
+            turn relies upon the Python DBAPI to transparently "begin"
+            transactions; there is **no need to explcitly begin transactions**
+            when using modern :class:`.Session` programming patterns.
+            In its default mode of ``autocommit=False``, the
+            :class:`.Session` does all of its work within
+            the context of a transaction, so as soon as you call
+            :meth:`.Session.commit`, the next transaction is implicitly
+            started when the next database operation is invoked.  See
+            :ref:`session_autocommit` for further background.
+
+        The method will raise an error if this :class:`.Session` is already
+        inside of a transaction, unless
+        :paramref:`~.Session.begin.subtransactions` or
+        :paramref:`~.Session.begin.nested` are specified.  A "subtransaction"
+        is essentially a code embedding pattern that does not affect the
+        transactional state of the database connection unless a rollback is
+        emitted, in which case the whole transaction is rolled back.  For
+        documentation on subtransactions, please see
+        :ref:`session_subtransactions`.
 
         :param subtransactions: if True, indicates that this
-         :meth:`~.Session.begin` can create a subtransaction if a transaction
-         is already in progress. For documentation on subtransactions, please
-         see :ref:`session_subtransactions`.
+         :meth:`~.Session.begin` can create a "subtransaction".
 
         :param nested: if True, begins a SAVEPOINT transaction and is equivalent
          to calling :meth:`~.Session.begin_nested`. For documentation on