Don't execute a ROLLBACK on close()/GC.

The command wasn't sent since 2.2.0 due to a bug, but after a ML
discussion this behaviour proved more correct so the bug has become a
feature.
This commit is contained in:
Daniele Varrazzo 2010-08-05 01:18:11 +01:00
parent cb1ef242a0
commit 2081ceffde
3 changed files with 38 additions and 16 deletions

View File

@ -1,3 +1,10 @@
2010-08-05 Daniele Varrazzo <daniele.varrazzo@gmail.com>
* psycopg/connection_int.c: don't execute a ROLLBACK on close()/GC.
The command wasn't sent since 2.2.0 due to a bug, but after a ML
discussion this behaviour proved more correct so the bug has become a
feature.
2010-07-18 Federico Di Gregorio <fog@initd.org> 2010-07-18 Federico Di Gregorio <fog@initd.org>
* Release 2.2.2. * Release 2.2.2.

View File

@ -67,10 +67,28 @@ The ``connection`` class
`~psycopg2.InterfaceError` will be raised if any operation is `~psycopg2.InterfaceError` will be raised if any operation is
attempted with the connection. The same applies to all cursor objects attempted with the connection. The same applies to all cursor objects
trying to use the connection. Note that closing a connection without trying to use the connection. Note that closing a connection without
committing the changes first will cause an implicit rollback to be committing the changes first will cause any pending change to be
performed (unless a different isolation level has been selected: see discarded as if a :sql:`ROLLBACK` was performed (unless a different
isolation level has been selected: see
`~connection.set_isolation_level()`). `~connection.set_isolation_level()`).
.. index::
single: PgBouncer; unclean server
.. versionchanged:: 2.2
previously an explicit :sql:`ROLLBACK` was issued by Psycopg on
`!close()`. The command could have been sent to the backend at an
inappropriate time, so Psycopg currently relies on the backend to
implicitly discard uncommitted changes. Some middleware are known
to behave incorrectly though when the connection is closed during
a transaction (when `~connection.status` is
`~psycopg2.extensions.STATUS_IN_TRANSACTION`), e.g. PgBouncer_
reports an ``unclean server`` and discards the connection. To
avoid this problem you can ensure to terminate the transaction
with a `~connection.commit()`/`~connection.rollback()` before
closing.
.. _PgBouncer: http://pgbouncer.projects.postgresql.org/
.. index:: .. index::
single: Exceptions; In the connection class single: Exceptions; In the connection class

View File

@ -743,18 +743,15 @@ conn_close(connectionObject *self)
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
pthread_mutex_lock(&self->lock); pthread_mutex_lock(&self->lock);
/* execute a forced rollback on the connection (but don't check the /* We used to call pq_abort_locked here, but the idea of issuing a
result, we're going to close the pq connection anyway */ * rollback on close/GC has been considered inappropriate.
if (self->pgconn && self->closed == 1) { *
PGresult *pgres = NULL; * Dropping the connection on the server has the same effect as the
char *error = NULL; * transaction is automatically rolled back. Some middleware, such as
* PgBouncer, have problem with connections closed in the middle of the
if (pq_abort_locked(self, &pgres, &error, &_save) < 0) { * transaction though: to avoid these problems the transaction should be
IFCLEARPGRES(pgres); * closed only in status CONN_STATUS_READY.
if (error) */
free (error);
}
}
if (self->closed == 0) if (self->closed == 0)
self->closed = 1; self->closed = 1;