]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
PostgreSQL dialect-level isolation_level parameter is legacy
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 8 Sep 2020 15:01:28 +0000 (11:01 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 8 Sep 2020 15:01:28 +0000 (11:01 -0400)
The isolation level section in the docs inadvertently
copied the PostgreSQL example using the PGDialect.isolation_level
parameter and not the execution_options.  ensure only
the execution_options version is documented.

Change-Id: I94e02ede62d3dded40e3fcbce8d04608dc063108

doc/build/core/connections.rst
lib/sqlalchemy/dialects/postgresql/base.py

index 989b721a04fc4f9f0da3f2c05a79354da16f983e..5597b83f14187e1b9186096930f87d4e8f4fb6ba 100644 (file)
@@ -387,10 +387,10 @@ Instead, each statement invoked upon the connection will commit any changes
 automatically; it sometimes also means that the connection itself will use
 fewer server-side database resources. For this reason and others, "autocommit"
 mode is often desirable for non-transactional applications that need to read
-individual tables or rows in isolation of a true ACID transaction.
+individual tables or rows outside the scope of a true ACID transaction.
 
-SQLAlchemy dialects can support these isolation levels as well as autocommit to
-as great a degree as possible.   The levels are set via family of
+SQLAlchemy dialects should support these isolation levels as well as autocommit
+to as great a degree as possible.   The levels are set via family of
 "execution_options" parameters and methods that are throughout the Core, such
 as the :meth:`_engine.Connection.execution_options` method.   The parameter is
 known as :paramref:`_engine.Connection.execution_options.isolation_level` and
@@ -407,30 +407,39 @@ the values are strings which are typically a subset of the following names::
 Not every DBAPI supports every value; if an unsupported value is used for a
 certain backend, an error is raised.
 
-For example, to force REPEATABLE READ on a specific connection::
+For example, to force REPEATABLE READ on a specific connection, then
+begin a transaction::
 
   with engine.connect().execution_options(isolation_level="REPEATABLE READ") as connection:
-      connection.execute(<statement>)
+      with connection.begin():
+          connection.execute(<statement>)
 
-The :paramref:`_engine.Connection.execution_options.isolation_level` option
-may also be set engine wide, as is often preferable.   It can be set either
-within :func:`_sa.create_engine` directly via the :paramref:`_sa.create_engine.execution_options`
-parameter::
+The :paramref:`_engine.Connection.execution_options.isolation_level` option may
+also be set engine wide, as is often preferable.  This is achieved by
+passing it within the :paramref:`_sa.create_engine.execution_options`
+parameter to :func:`_sa.create_engine`::
 
 
     from sqlalchemy import create_engine
 
     eng = create_engine(
         "postgresql://scott:tiger@localhost/test",
-        isolation_level='REPEATABLE READ'
+        execution_options={
+            "isolation_level": "REPEATABLE READ"
+        }
     )
 
-Or for an application that chooses between multiple levels, as may be the case
-for the use of "AUTOCOMMIT" to switch between "transactional" and "read-only"
-engines, the :meth:`_engine.Engine.execution_options` method will provide a shallow
-copy of the :class:`_engine.Engine` that will apply the given isolation
-level to all connections::
+With the above setting, the DBAPI connection will be set to use a
+``"REPEATABLE READ"`` isolation level setting for each new transaction
+begun.
 
+An application that frequently chooses to run operations within different
+isolation levels may wish to create multiple "sub-engines" of a lead
+:class:`_engine.Engine`, each of which will be configured to a different
+isolation level.  One such use case is an application that has operations
+that break into "transactional" and "read-only" operations, a separate
+:class:`_engine.Engine` that makes use of ``"AUTOCOMMIT"`` may be
+separated off from the main engine::
 
     from sqlalchemy import create_engine
 
@@ -439,9 +448,11 @@ level to all connections::
     autocommit_engine = eng.execution_options(isolation_level="AUTOCOMMIT")
 
 
-Above, both ``eng`` and ``autocommit_engine`` share the same dialect
-and connection pool.  However the "AUTOCOMMIT" mode will be set upon connections
-when they are acquired from the ``autocommit_engine``.
+Above, the :meth:`_engine.Engine.execution_options` method creates a shallow
+copy of the original :class:`_engine.Engine`.  Both ``eng`` and
+``autocommit_engine`` share the same dialect and connection pool.  However, the
+"AUTOCOMMIT" mode will be set upon connections when they are acquired from the
+``autocommit_engine``.
 
 The isolation level setting, regardless of which one it is, is unconditionally
 reverted when a connection is returned to the connection pool.
index 8eb116111d826372f00bd66d0c79a339d56680d3..105e93c9dec0f977b64d271989cda7377817fe50 100644 (file)
@@ -117,38 +117,46 @@ The CREATE TABLE for the above :class:`_schema.Table` object would be:
 Transaction Isolation Level
 ---------------------------
 
-All PostgreSQL dialects support setting of transaction isolation level
-both via a dialect-specific parameter
-:paramref:`_sa.create_engine.isolation_level` accepted by
-:func:`_sa.create_engine`,
-as well as the :paramref:`.Connection.execution_options.isolation_level`
-argument as passed to :meth:`_engine.Connection.execution_options`.
-When using a non-psycopg2 dialect, this feature works by issuing the command
-``SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL <level>`` for
-each new connection.  For the special AUTOCOMMIT isolation level,
-DBAPI-specific techniques are used.
+Most SQLAlchemy dialects support setting of transaction isolation level
+using the :paramref:`_sa.create_engine.execution_options` parameter
+at the :func:`_sa.create_engine` level, and at the :class:`_engine.Connection`
+level via the :paramref:`.Connection.execution_options.isolation_level`
+parameter.
+
+For PostgreSQL dialects, this feature works either by making use of the
+DBAPI-specific features, such as psycopg2's isolation level flags which will
+embed the isolation level setting inline with the ``"BEGIN"`` statement, or for
+DBAPIs with no direct support by emitting ``SET SESSION CHARACTERISTICS AS
+TRANSACTION ISOLATION LEVEL <level>`` ahead of the ``"BEGIN"`` statement
+emitted by the DBAPI.   For the special AUTOCOMMIT isolation level,
+DBAPI-specific techniques are used which is typically an ``.autocommit``
+flag on the DBAPI connection object.
 
 To set isolation level using :func:`_sa.create_engine`::
 
     engine = create_engine(
         "postgresql+pg8000://scott:tiger@localhost/test",
-        isolation_level="READ UNCOMMITTED"
+        execution_options={
+            "isolation_level": "REPEATABLE READ"
+        }
     )
 
 To set using per-connection execution options::
 
-    connection = engine.connect()
-    connection = connection.execution_options(
-        isolation_level="READ COMMITTED"
-    )
+    with engine.connect() as conn:
+        conn = conn.execution_options(
+            isolation_level="REPEATABLE READ"
+        )
+        with conn.begin():
+            # ... work with transaction
 
-Valid values for ``isolation_level`` include:
+Valid values for ``isolation_level`` on most PostgreSQL dialects include:
 
 * ``READ COMMITTED``
 * ``READ UNCOMMITTED``
 * ``REPEATABLE READ``
 * ``SERIALIZABLE``
-* ``AUTOCOMMIT`` - on psycopg2 / pg8000 only
+* ``AUTOCOMMIT``
 
 .. seealso::
 
@@ -2684,6 +2692,10 @@ class PGDialect(default.DefaultDialect):
         **kwargs
     ):
         default.DefaultDialect.__init__(self, **kwargs)
+
+        # the isolation_level parameter to the PGDialect itself is legacy.
+        # still works however the execution_options method is the one that
+        # is documented.
         self.isolation_level = isolation_level
         self._json_deserializer = json_deserializer
         self._json_serializer = json_serializer