]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
clarify autoflush setting does not apply to commit
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 8 Apr 2022 14:36:50 +0000 (10:36 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 8 Apr 2022 14:46:23 +0000 (10:46 -0400)
Change-Id: Icad0f3bd071422b8d1af204c9a1193a9ce6124ba
References: #7916
(cherry picked from commit ed2b29dc344c9cb65745c767b755f82d913695b8)

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

index d60db4d73c78b78ddcf508b036a8c9032d79ec49..8d3ebb735f2c796a9104a5dd6bf71dccf7791336 100644 (file)
@@ -424,39 +424,53 @@ a :term:`2.0-style` :meth:`_orm.Session.execute` call, as well as within the
 committed. It also occurs before a SAVEPOINT is issued when
 :meth:`~.Session.begin_nested` is used.
 
-Regardless of the autoflush setting, a flush can always be forced by issuing
-:meth:`~.Session.flush`::
+A :class:`.Session` flush can be forced at any time by calling the
+:meth:`~.Session.flush` method::
 
     session.flush()
 
-The "flush-on-Query" aspect of the behavior can be disabled by constructing
-:class:`.sessionmaker` with the flag ``autoflush=False``::
+The flush which occurs automatically within the scope of
+:meth:`_orm.Session.execute`, :class:`_query.Query`, as well as other
+:class:`.Session` methods such as :meth:`.Session.merge` (but **not** including
+the :meth:`.Session.commit` method) is known as **autoflush**. This "autoflush"
+behavior can be disabled by constructing a :class:`.Session` or
+:class:`.sessionmaker` passing the :paramref:`.Session.autoflush` parameter as
+``False``::
 
     Session = sessionmaker(autoflush=False)
 
-Additionally, autoflush can be temporarily disabled by setting the
-``autoflush`` flag at any time::
-
-    mysession = Session()
-    mysession.autoflush = False
-
-More conveniently, it can be turned off within a context managed block using :attr:`.Session.no_autoflush`::
+Additionally, autoflush can be temporarily disabled within the flow
+of using a :class:`.Session` using the
+:attr:`.Session.no_autoflush` context manager::
 
     with mysession.no_autoflush:
         mysession.add(some_object)
         mysession.flush()
 
-The flush process *always* occurs within a transaction, even if the
-:class:`~sqlalchemy.orm.session.Session` has been configured with
-``autocommit=True``, a setting that disables the session's persistent
-transactional state. If no transaction is present,
-:meth:`~.Session.flush` creates its own transaction and
-commits it. Any failures during flush will always result in a rollback of
-whatever transaction is present. If the Session is not in ``autocommit=True``
-mode, an explicit call to :meth:`~.Session.rollback` is
-required after a flush fails, even though the underlying transaction will have
-been rolled back already - this is so that the overall nesting pattern of
-so-called "subtransactions" is consistently maintained.
+The flush process **always occurs** when the :meth:`.Session.commit` method is
+called, regardless of any "autoflush" settings, when the :class:`.Session` has
+remaining pending changes to process.
+
+The flush process *always* occurs within a transaction, (subject to the
+:ref:`isolation level <session_transaction_isolation>` of the database
+transaction), provided that the DBAPI is not in
+:ref:`driver level autocommit <dbapi_autocommit>` mode. This includes even if
+the :class:`~sqlalchemy.orm.session.Session` has been configured with the
+deprecated :paramref:`_orm.Session.autocommit` setting, which disables the
+session's persistent transactional state. If no transaction is present,
+:meth:`~.Session.flush` creates its own transaction and commits it. This means
+that assuming the database connection is providing for :term:`atomicity` within
+its transactional settings, if any individual DML statement inside the flush
+fails, the entire operation will be rolled back.
+
+Outside of using :paramref:`_orm.Session.autocommit`, when a failure occurs
+within a flush, in order to continue using that same :class:`_orm.Session`, an
+explicit call to :meth:`~.Session.rollback` is required after a flush fails,
+even though the underlying transaction will have been rolled back already (even
+if the database driver is technically in driver-level autocommit mode). This is
+so that the overall nesting pattern of so-called "subtransactions" is
+consistently maintained. The FAQ section :ref:`faq_session_rollback` contains a
+more detailed description of this behavior.
 
 .. _session_expiring:
 
index d5a80953d6ed69f35f86c842583a321938a72c35..315a1254fdc1076621450285a4e337b94d80854d 100644 (file)
@@ -1003,6 +1003,10 @@ class Session(_SessionClassMethods):
            :meth:`~.Session.flush` are rarely needed; you usually only need to
            call :meth:`~.Session.commit` (which flushes) to finalize changes.
 
+           .. seealso::
+
+               :ref:`session_flushing` - additional background on autoflush
+
         :param bind: An optional :class:`_engine.Engine` or
            :class:`_engine.Connection` to
            which this ``Session`` should be bound. When specified, all SQL