From: chrispy Date: Sun, 20 Apr 2025 13:00:40 +0000 (-0400) Subject: add docs for using Psycopg 3 connection pooling (see SQLAlchemy discussion #12522) X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=865a7d87555ee24f047364a43a3ce787a8054730;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git add docs for using Psycopg 3 connection pooling (see SQLAlchemy discussion #12522) Signed-off-by: chrispy --- diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg.py b/lib/sqlalchemy/dialects/postgresql/psycopg.py index 4df6f8a4fa..d41bdae7e7 100644 --- a/lib/sqlalchemy/dialects/postgresql/psycopg.py +++ b/lib/sqlalchemy/dialects/postgresql/psycopg.py @@ -59,6 +59,81 @@ The asyncio version of the dialect may also be specified explicitly using the dialect shares most of its behavior with the ``psycopg2`` dialect. Further documentation is available there. +Connection Pooling +------------------ + +Applications with multiple concurrent users should use connection pooling. A +minimal sized connection pool is also beneficial for long-running, single-user +applications that do not frequently use a connection. + +``psycopg`` provides its own connection pool implementation that may be used +in place of SQLAlchemy's pooling functionality. This pool implementation +provides support for fixed and dynamic pool sizes (including automatic +downsizing for unused connections), connection health pre-checks, and support +for both synchronous and asynchronous code environments. + +To take advantage of ``psycopg``'s pool, + +- Create a custom ``psycopg.Connection`` class that returns "closed" + checked-out pool connections to the pool. +- Create a ``psycopg_pool.ConnectionPool`` instance that uses this connection + class along with the desired pool configuration. +- Create a ``sqlalchemy.engine`` that: + + - Sets the ``create_engine.pool_class`` parameter to ``NullPool`` to disable + SQLAlchemy's pooling. + - Sets the ``create_engine.creator`` parameter to use the Psycopg 3 pool to + obtain new connections. + +For example:: + + import psycopg + import psycopg_pool + from sqlalchemy import create_engine + from sqlalchemy.pool import NullPool + + class MyConnection(psycopg.Connection): + def close(self): + if pool := getattr(self, "_pool", None): + # Connection currently checked out from its pool; + # instead of closing it, return it to the pool. + pool.putconn(self) + else: + # Connection being removed from its pool, or not part of any pool; + # close the connection for real. + super().close() + + mypool = psycopg_pool.ConnectionPool( + connection_class=MyConnection, + conninfo="postgresql://scott:tiger@localhost/test", + min_size=1, # Minimum pool size + max_size=5, # Maximum pool size + max_idle=60, # Maximum idle time (seconds) for unused pool connections + ) + + engine = create_engine( + url="postgresql+psycopg://", # Only need the dialect now + poolclass=NullPool, # Disable SQLAlchemy's default connection pool + creator=mypool.getconn, # Use Psycopg 3 connection pool to obtain connections + ) + +The resulting engine may then be used normally. Internally, Psycopg 3 handles +connection pooling:: + + with engine.connect() as conn: + print(conn.scalar(text("select 1 from dual"))) + +``psycopg_pool.ConnectionPool`` uses the ``logging`` module to log key pool +operations to the ``psycopg.pool`` logger. To monitor or debug logging +behaviors, you can set the threshold for this logger to ``INFO``. + +.. seealso:: + + `Connection pools `_ - + the Psycopg 3 documentation for ``psycopg_pool.ConnectionPool``, + which provides more information on available configuration parameters, + logging, and more. + Using a different Cursor class ------------------------------