Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to start transactions in autocommit mode #941

Closed
anarazel opened this issue Jul 2, 2019 · 15 comments
Closed

Allow to start transactions in autocommit mode #941

anarazel opened this issue Jul 2, 2019 · 15 comments
Milestone

Comments

@anarazel
Copy link

anarazel commented Jul 2, 2019

Hi,

using autocommit mode can be quite useful for some long running applications, to make it less likely that transactions are accidentally left open, and to perform operations like VACUUM etc. psycopg provides for that by allowing to set autocommit to true.

Unfortunately I think that's too large a hammer in a lot of cases. What I think is commonly desired is being able to granularly choose the desired behaviour, but psycopg doesn't allow that currently.

E.g. even when in autocommit mode, one might want to explicitly use a transaction. But that doesn't really work well right now. Approaches I considered:

  1. Use con.begin() - which doesn't exist
  2. Just start a transaction using .execute() - but that breaks con.commit(), because:
    https://github.com/psycopg/psycopg2/blob/master/psycopg/pqpath.c#L396
    if (conn->autocommit || conn->status != CONN_STATUS_BEGIN) {
        Dprintf("pq_commit: no transaction to commit");
        retvalue = 0;
}

even though the connection knows that it's in a transaction, it ignores that fact.

While I obviously just could commit using .execute('COMMIT') that seems too likely to break assumptions of other code.

  1. Disable autocommit for a single transaction:
psycopg2.ProgrammingError: set_session cannot be used inside a transaction

While I could work around that by resetting autocommit later, that requires exception handling etc.

What I think a sensible approach would be:

  1. Have pq_commit() actually commit, even if autocommit mode is on, if there's a transaction in progress - the transaction status is known at the client side
  2. Provide .begin(), to explicitly start a transaction (probably erroring out if there already is one in progress)
  3. Have a context manager for transactions (rather than just connections and cursors). Probably just return one from con.begin().

Regards

Andres

@dvarrazzo
Copy link
Member

Hello Andres.

I think there are a few things that can be done, yes. First a correction: it's a bit surprising but the connection context manager doesn't exit with close, but it terminates a transaction.

I don't have code handy but I guess entering the CM with an autocommit transaction is a no-op.

So I see two easy improvements:

  • change __enter__ to begin a transaction even if the connection is autocommit. It is a change in behaviour, but I don't think anyone really does it. We could introduce a warning in the current maintenance branch and change behaviour in the next major release.

  • change commit() and rollback() to terminate the transaction on autocommit too, so that the connection would behave as expected even if someone issued a manual BEGIN (I don't think there are breaking assumptions around in the code).

In case of autocommit it would be better tracking the status using libpq PQtransactionStatus instead of conn->status (even betterer would be to always use the libpq, probably...)

Would you like to work on these changes in a MR?

@dvarrazzo dvarrazzo changed the title [feature request] allow to start transactions in autocommit mode Allow to start transactions in autocommit mode Oct 27, 2019
@dvarrazzo dvarrazzo added this to the 2.9 milestone Oct 27, 2019
@and-semakin
Copy link

My current workaround (that relies on 3rd approach of @anarazel) to this issue is following:

from contextlib import contextmanager
from typing import Iterator

from psycopg2.extensions import connection as PgConnection


@contextmanager
def transaction_in_autocommit_mode(connection: PgConnection) -> Iterator[None]:
    connection.rollback()
    connection.autocommit = False
    try:
        with connection:
            yield
    finally:
        connection.autocommit = True

Seems to be working as expected:

In [43]: def get_txid(cur):
    ...:     cur.execute("SELECT txid_current()")
    ...:     txid, = cur.fetchone()
    ...:     return txid
    ...:

In [44]: with transaction_in_autocommit_mode(conn):
    ...:     with conn.cursor() as cur:
    ...:         print(get_txid(cur))
    ...:         print(get_txid(cur))
    ...:
654
654

@tometzky
Copy link

Based on @and-semakin's code I've created an elegant (IMHO) connection factory with autocommit and explicit transactions:

"""AutocommitConnection"""

import contextlib
import sys
import typing

import psycopg2  # type: ignore


class AutocommitConnection(
    psycopg2.extensions.connection
):  # pylint: disable=too-few-public-methods
    """Connection factory with autocommit and explicit transactions"""

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.set_session(autocommit=True)

    @contextlib.contextmanager
    def transaction(self) -> typing.Iterator[None]:
        """Context manager to encapsulate a transaction"""
        self.set_session(autocommit=False)
        try:
            with self:
                yield
        finally:
            self.set_session(autocommit=True)

# Example usage:
# Uses default connection or environmental variables like PGHOST PGDATABASE PGUSER PGPASSWORD
conn: AutocommitConnection = psycopg2.connect(
    "", connection_factory=AutocommitConnection
)
with conn.cursor() as cur:
    cur.execute("create temporary table test_autocommit(id int)")
    cur.execute("insert into test_autocommit values (1)")
    try:
        cur.execute("insert into test_autocommit values ('A')")
    except psycopg2.Error as err:
        print("Error:", err, file=sys.stderr)
    with conn.transaction():
        cur.execute("insert into test_autocommit values (2)")
        cur.execute("insert into test_autocommit values (3)")
        # Automatic commit
    with conn.transaction():
        cur.execute("insert into test_autocommit values (4)")
        try:
            cur.execute("insert into test_autocommit values ('A')")
        except psycopg2.Error as err:
            print("Error:", err, file=sys.stderr)
        # Automatic rollback
    with conn.transaction():
        cur.execute("insert into test_autocommit values (5)")
        conn.rollback()
        # Explicit rollback

# Also works in one line:
with conn.cursor() as cur, conn.transaction():
    cur.execute("insert into test_autocommit values (6)")
    cur.execute("insert into test_autocommit values (7)")
with conn.cursor() as cur, conn.transaction():
    cur.execute("insert into test_autocommit values (8)")
    cur.execute("insert into test_autocommit values (9)")
    conn.rollback()

with conn.cursor() as cur:
    cur.execute("select id from test_autocommit order by id")
    for (val,) in cur:
        print(val)
    # It should print 1, 2, 3, 6, 7
    # It should not print 4, 5, 8, nor 9 as they were rolled-back

@bortzmeyer
Copy link

In the mean time, it could be cool to document the fact that, in autocommit=True mode, conn.commit() is silently ignored and that you have to call cursor.execute("COMMIT") explicitely.

@asqui
Copy link
Contributor

asqui commented May 9, 2021

This might be of interest: https://github.com/asqui/psycopg-nestedtransactions

It's a Transaction context manager that abstracts away needing to manipulate autocommit.

Broadly similar to the AutocommitConnection above, but also supports nested transactions (implemented using savepoints) and forms the basis for the similar transaction functionality that is built-in to psycopg3.

@rachelcdavies
Copy link

rachelcdavies commented Jun 17, 2021

We use conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) when working with Redshift and the new pyscopg2 release 2.9 that adds "with connection starts a transaction on autocommit transactions too" causes problems for us.

There are certain Redshift commands that cannot run in a transaction. For example,
"Amazon Invalid operation: ALTER TABLE ALTER COLUMN cannot run inside a transaction block;"
We've pinned our code to use 2.8 for now and will raise an issue.

@jimbojd72
Copy link

jimbojd72 commented Jun 18, 2021

import psycopg2
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT

def database_setup(request, postgresql_process):
    with psycopg2.connect(
        dbname="postgres",
        user=postgresql_process.user,
        host=postgresql_process.host,
        port=postgresql_process.port,
    ) as conn:
        conn.autocommit = True
        conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
        with conn.cursor() as cursor:
            cursor.execute(f'CREATE DATABASE "{TEST_DATABASE}";')

I reproduce what @rachelcdavies is having as well on 2.9.1. I added ISOLATION_LEVEL_AUTOCOMMIT part but I still received psycopg2.errors.ActiveSqlTransaction: CREATE DATABASE cannot run inside a transaction block

Any solutions? I will need to rollback as well or stop using a with statement I guess

Edit:

Reverting to the old way with a try/finally also did the trick for me, but not really clean.

@pytest.fixture(scope="session")
def database_setup(request, postgresql_process):

    conn = None
    try:
        conn = psycopg2.connect(
            dbname="postgres",
            user=postgresql_process.user,
            host=postgresql_process.host,
            port=postgresql_process.port,
        )
        conn.autocommit = True
        with conn.cursor() as cursor:
            cursor.execute(f'CREATE DATABASE "{TEST_DATABASE}";')
    finally:
        if conn:
            conn.close()

@dvarrazzo
Copy link
Member

Yes, that's the way to do it: don't use a with block if you don't want a transaction to start.

@nicktimko
Copy link

@dvarrazzo what if you want your connection to be cleaned up automatically? I guess I get changing the default behavior as that's more common, but CREATE DATABASE ... queries or the like should also be acommodated

@dvarrazzo
Copy link
Member

@nicktimko using with you are not cleaning any resource. Before 2.9 you are not doing anything at all. Now you are opening and closing a transaction. If you want the behaviour you expect (which is reasonable), freeing resources at the end of the with block, you have to move to psycopg 3.

LinqLover added a commit to Museum-Barberini/Barberini-Analytics that referenced this issue Aug 19, 2021
Remove context handler for connection. Complements psycopg/psycopg2#941.
chrisjsewell added a commit to aiidateam/pgsu that referenced this issue Aug 30, 2021
Addresses aiidateam/aiida-core#5002:
In v2.9, the context manager opens a transaction, but databases cannot be created within them.
The fix is taken from: psycopg/psycopg2#941 (comment)
bnavigator added a commit to bnavigator/pytest-plugins that referenced this issue Oct 17, 2021
Psycopg 2.9 does uses transaction blocks withing context managers,
which is not allowed for CREATE DATABASE
psycopg/psycopg2#941
bnavigator added a commit to bnavigator/pytest-plugins that referenced this issue Oct 17, 2021
Psycopg 2.9 uses transaction blocks withing context managers,
which is not allowed for CREATE DATABASE
psycopg/psycopg2#941
@vsalvino
Copy link

vsalvino commented Nov 4, 2021

Also just got bitten by this "feature" from psycopg2==2.9. I do not see any guidance in the documentation on how to turn off? For example, we are using:

with psycopg2.connect(...) as cnx:
    cnx.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
    with cnx.cursor() as cursor:
        # Create database.
        try:
            cursor.execute('CREATE DATABASE "name" WITH OWNER="owner";')
        except psycopg2.errors.DuplicateDatabase as exc:
            print(exc)

Instead of psycopg2.errors.DuplicateDatabase it now throws the following error: psycopg2.errors.InFailedSqlTransaction

@dvarrazzo
Copy link
Member

@vsalvino Just don't use with psycopg2.connect(...) as cnx, which is documented to start a transaction.

@vsalvino
Copy link

vsalvino commented Nov 4, 2021

@dvarrazzo thanks for the quick reply... based on some further research I think we might take this as an opportunity to try out psycopg3, which seems to be able to disable the behavior in the connection.

Linking here for others watching the thread: https://www.psycopg.org/psycopg3/docs/basic/transactions.html#autocommit-transactions

@dvarrazzo
Copy link
Member

@vsalvino Yes, unfortunately the psycopg2 connection context was not a happy design. Psycopg 3 might behave in a less surprising way.

mergify bot referenced this issue in andrewbolster/bolster Nov 15, 2021
Bumps [psycopg2-binary](https://github.com/psycopg/psycopg2) from 2.9.1 to 2.9.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/psycopg/psycopg2/blob/master/NEWS">psycopg2-binary's changelog</a>.</em></p>
<blockquote>
<h2>Current release</h2>
<p>What's new in psycopg 2.9.2
^^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<ul>
<li>Raise <code>ValueError</code> for dates &gt;= Y10k (:ticket:<code>[#1307](https://github.com/psycopg/psycopg2/issues/1307)</code>).</li>
<li><code>~psycopg2.errorcodes</code> map and <code>~psycopg2.errors</code> classes updated to
PostgreSQL 14.</li>
<li>Add preliminary support for Python 3.11 (:tickets:<code>[#1376](psycopg/psycopg2#1376), [#1386](https://github.com/psycopg/psycopg2/issues/1386)</code>).</li>
<li>Wheel package compiled against OpenSSL 1.1.1l and PostgreSQL 14.1
(:ticket:<code>[#1388](https://github.com/psycopg/psycopg2/issues/1388)</code>).</li>
</ul>
<p>What's new in psycopg 2.9.1
^^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<p>Fix regression with named <code>sql.Placeholder</code> (:ticket:<code>[#1291](https://github.com/psycopg/psycopg2/issues/1291)</code>).</p>
<h2>What's new in psycopg 2.9</h2>
<ul>
<li><code>with connection</code> starts a transaction on autocommit transactions too
(:ticket:<code>[#941](https://github.com/psycopg/psycopg2/issues/941)</code>).</li>
<li>Timezones with fractional minutes are supported on Python 3.7 and following
(:ticket:<code>[#1272](https://github.com/psycopg/psycopg2/issues/1272)</code>).</li>
<li>Escape table and column names in <code>~cursor.copy_from()</code> and
<code>~cursor.copy_to()</code>.</li>
<li>Connection exceptions with sqlstate <code>08XXX</code> reclassified as
<code>~psycopg2.OperationalError</code> (a subclass of the previously used
<code>~psycopg2.DatabaseError</code>) (:ticket:<code>[#1148](https://github.com/psycopg/psycopg2/issues/1148)</code>).</li>
<li>Include library dirs required from libpq to work around MacOS build problems
(:ticket:<code>[#1200](https://github.com/psycopg/psycopg2/issues/1200)</code>).</li>
</ul>
<p>Other changes:</p>
<ul>
<li>Dropped support for Python 2.7, 3.4, 3.5 (:tickets:<code>[#1198](psycopg/psycopg2#1198), [#1000](psycopg/psycopg2#1000), [#1197](https://github.com/psycopg/psycopg2/issues/1197)</code>).</li>
<li>Dropped support for mx.DateTime.</li>
<li>Use <code>datetime.timezone</code> objects by default in datetime objects instead of
<code>~psycopg2.tz.FixedOffsetTimezone</code>.</li>
<li>The <code>psycopg2.tz</code> module is deprecated and scheduled to be dropped in the
next major release.</li>
<li>Provide :pep:<code>599</code> wheels packages (manylinux2014 tag) for i686 and x86_64
platforms.</li>
<li>Provide :pep:<code>600</code> wheels packages (manylinux_2_24 tag) for aarch64 and
ppc64le platforms.</li>
<li>Wheel package compiled against OpenSSL 1.1.1k and PostgreSQL 13.3.</li>
<li>Build system for Linux/MacOS binary packages moved to GitHub Actions.</li>
</ul>

</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a href="https://github.com/psycopg/psycopg2/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=psycopg2-binary&package-manager=pip&previous-version=2.9.1&new-version=2.9.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>
@hoxu
Copy link

hoxu commented Dec 14, 2021

We ran into an exception caused by this changed psycopg2 behavior when upgrading from Python 2 to Python 3, because it seems the latest psycopg2 version for Python 2 is 2.8.6, and Python 3 has 2.9.2, with this problematic transaction change. In our case the exception was from Redshift as well:

psycopg2.errors.ActiveSqlTransaction: ALTER EXTERNAL TABLE cannot run inside a transaction block

And the affected code is:

    with psycopg2.connect(...) as conn:
        conn.set_session(autocommit=True)
        with conn.cursor() as curs:

Kind of confusing to see an exception about not being able to run inside a transaction, when the code clearly seems to be setting autocommits on.

I think it would be useful to have a list of workarounds with code examples on this issue (and perhaps changelog), because this is clearly a breaking change from 2.8.x to 2.9.

Workaround 1: pin psycopg2 dependency to 2.8.6.

mergify bot referenced this issue in andrewbolster/bolster Dec 29, 2021
Bumps [psycopg2-binary](https://github.com/psycopg/psycopg2) from 2.9.2 to 2.9.3.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/psycopg/psycopg2/blob/master/NEWS">psycopg2-binary's changelog</a>.</em></p>
<blockquote>
<h2>Current release</h2>
<p>What's new in psycopg 2.9.3
^^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<ul>
<li>Alpine (musl) wheels now available (:ticket:<code>[#1148](https://github.com/psycopg/psycopg2/issues/1148)</code>).</li>
</ul>
<p>What's new in psycopg 2.9.2
^^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<ul>
<li>Raise <code>ValueError</code> for dates &gt;= Y10k (:ticket:<code>[#1307](https://github.com/psycopg/psycopg2/issues/1307)</code>).</li>
<li><code>~psycopg2.errorcodes</code> map and <code>~psycopg2.errors</code> classes updated to
PostgreSQL 14.</li>
<li>Add preliminary support for Python 3.11 (:tickets:<code>[#1376](psycopg/psycopg2#1376), [#1386](https://github.com/psycopg/psycopg2/issues/1386)</code>).</li>
<li>Wheel package compiled against OpenSSL 1.1.1l and PostgreSQL 14.1
(:ticket:<code>[#1388](https://github.com/psycopg/psycopg2/issues/1388)</code>).</li>
</ul>
<p>What's new in psycopg 2.9.1
^^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<p>Fix regression with named <code>sql.Placeholder</code> (:ticket:<code>[#1291](https://github.com/psycopg/psycopg2/issues/1291)</code>).</p>
<h2>What's new in psycopg 2.9</h2>
<ul>
<li><code>with connection</code> starts a transaction on autocommit transactions too
(:ticket:<code>[#941](https://github.com/psycopg/psycopg2/issues/941)</code>).</li>
<li>Timezones with fractional minutes are supported on Python 3.7 and following
(:ticket:<code>[#1272](https://github.com/psycopg/psycopg2/issues/1272)</code>).</li>
<li>Escape table and column names in <code>~cursor.copy_from()</code> and
<code>~cursor.copy_to()</code>.</li>
<li>Connection exceptions with sqlstate <code>08XXX</code> reclassified as
<code>~psycopg2.OperationalError</code> (a subclass of the previously used
<code>~psycopg2.DatabaseError</code>) (:ticket:<code>[#1148](https://github.com/psycopg/psycopg2/issues/1148)</code>).</li>
<li>Include library dirs required from libpq to work around MacOS build problems
(:ticket:<code>[#1200](https://github.com/psycopg/psycopg2/issues/1200)</code>).</li>
</ul>
<p>Other changes:</p>
<ul>
<li>Dropped support for Python 2.7, 3.4, 3.5 (:tickets:<code>[#1198](psycopg/psycopg2#1198), [#1000](psycopg/psycopg2#1000), [#1197](https://github.com/psycopg/psycopg2/issues/1197)</code>).</li>
<li>Dropped support for mx.DateTime.</li>
<li>Use <code>datetime.timezone</code> objects by default in datetime objects instead of
<code>~psycopg2.tz.FixedOffsetTimezone</code>.</li>
<li>The <code>psycopg2.tz</code> module is deprecated and scheduled to be dropped in the
next major release.</li>
<li>Provide :pep:<code>599</code> wheels packages (manylinux2014 tag) for i686 and x86_64</li>
</ul>

</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a href="https://github.com/psycopg/psycopg2/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=psycopg2-binary&package-manager=pip&previous-version=2.9.2&new-version=2.9.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>
Spindel added a commit to Spindel/housekeeper that referenced this issue Oct 23, 2022
CONCURRENT indexes are only valid if they are not created inside a
transaction block.

psycopg2 has started to automatically emit BEGIN / END transaction when
using the "with "  context manager, thus causing explicit transactions
to happen for us here.

See: psycopg/psycopg2#941

This means that we now need to stop using concurrently as we may or may
not be inside a transaction block.
Spindel added a commit to Spindel/housekeeper that referenced this issue Oct 23, 2022
With psycopg2 we cannot use the "connect()" as a conext manager anymore
without getting an transaction automatically opened.

This means we need to replace it with our own wrapper function that does
the same, but that also enables autocommit mode for the connection.

This was forced by the upstream behaviour change documented:

>
> Yes, that's the way to do it: don't use a with block if you don't want
> a transaction to start.

psycopg/psycopg2#941 (comment)
benesch added a commit to benesch/materialize that referenced this issue Oct 14, 2023
v2.9 changed the autocommit handling of `with` blocks, so we can no
longer create the connection using `with`. See [0] for details.

[0]: psycopg/psycopg2#941
nrainer-materialize pushed a commit to nrainer-materialize/materialize that referenced this issue Oct 17, 2023
v2.9 changed the autocommit handling of `with` blocks, so we can no
longer create the connection using `with`. See [0] for details.

[0]: psycopg/psycopg2#941
tristan957 added a commit to neondatabase/neon that referenced this issue Nov 12, 2024
psycopg2 has the following warning related to autocommit:

> By default, any query execution, including a simple SELECT will start
> a transaction: for long-running programs, if no further action is
> taken, the session will remain “idle in transaction”, an undesirable
> condition for several reasons (locks are held by the session, tables
> bloat…). For long lived scripts, either ensure to terminate a
> transaction as soon as possible or use an autocommit connection.

In the 2.9 release notes, psycopg2 also made the following change:

> `with connection` starts a transaction on autocommit transactions too

Some of these connections are indeed long-lived, so we were retaining
tons of WAL on the endpoints because we had a transaction pinned in the
past.

Link: https://www.psycopg.org/docs/news.html#what-s-new-in-psycopg-2-9
Link: psycopg/psycopg2#941
Signed-off-by: Tristan Partin <tristan@neon.tech>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests