From: Mike Bayer Date: Fri, 8 Apr 2022 14:36:50 +0000 (-0400) Subject: clarify autoflush setting does not apply to commit X-Git-Tag: rel_2_0_0b1~367 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed2b29dc344c9cb65745c767b755f82d913695b8;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git clarify autoflush setting does not apply to commit Change-Id: Icad0f3bd071422b8d1af204c9a1193a9ce6124ba References: #7916 --- diff --git a/doc/build/orm/session_basics.rst b/doc/build/orm/session_basics.rst index 1755c62fe7..c877ae3b84 100644 --- a/doc/build/orm/session_basics.rst +++ b/doc/build/orm/session_basics.rst @@ -424,41 +424,51 @@ 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 (subject -to the :ref:`isolation level `_ of the -database transaction), which is -*never* committed automatically; the :meth:`_orm.Session.commit` method -must be called, or an appropriate context manager which does the same -thing must be used, in order for the database changes to be committed. - -Any failures during flush will always result in a rollback of -whatever transaction is present. In order to continue using that +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. + +As the :class:`.Session` only invokes SQL to the database within the context of +a :term:`DBAPI` transaction, all "flush" operations themselves only occur within a +database transaction (subject to the +:ref:`isolation level ` of the database +transaction), provided that the DBAPI is not in +:ref:`driver level autocommit ` mode. 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. + +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 - this is so that the overall nesting pattern of -so-called "subtransactions" is consistently maintained. +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. .. seealso:: diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index 58820fef62..6279c17fbc 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -1104,6 +1104,10 @@ class Session(_SessionClassMethods): not be called repeatedly in order for database queries to retrieve results. + .. 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 @@ -4022,6 +4026,11 @@ class sessionmaker(_SessionClassMethods): objects. Defaults to :class:`.Session`. :param autoflush: The autoflush setting to use with newly created :class:`.Session` objects. + + .. seealso:: + + :ref:`session_flushing` - additional background on autoflush + :param expire_on_commit=True: the :paramref:`_orm.Session.expire_on_commit` setting to use with newly created :class:`.Session` objects.