Connection Pooling¶
接続プールは、効率的な再利用のために長時間実行される接続をメモリー内に保持したり、アプリケーションが同時に使用する可能性のある接続の総数を管理したりするために使用される標準的な手法です。
特にサーバー・サイドのWebアプリケーションの場合、接続プールは、メモリー内のアクティブなデータベース接続のプールを維持するための標準的な方法であり、この”プール”は要求間で再利用されます。
SQLAlchemyには、 Engine
と統合される接続プールの実装がいくつか含まれています。また、通常のDBAPIアプローチにプーリングを追加したいアプリケーションで直接使用することもできます。
Connection Pool Configuration¶
ほとんどの場合、 create_engine()
関数が返す Engine
には QueuePool
が統合されていて、適切なプーリングのデフォルトで事前に設定されています。プーリングを有効にする方法を学ぶためだけにこのセクションを読んでいるのであれば、おめでとうございます!もう終わりました。
最も一般的な QueuePool
チューニングパラメータは、キーワード引数として create_engine()
に直接渡すことができます:pool_size、max_overflow、pool_recycle、pool_timeout。例:
engine = create_engine(
"postgresql+psycopg2://me@localhost/mydb", pool_size=20, max_overflow=0
)
すべてのSQLAlchemyプール実装に共通しているのは、どの実装も接続を”事前作成”しないということです。すべての実装は、接続を作成する前に最初に使用されるまで待機します。その時点で、追加の接続に対する追加の同時チェックアウト要求が行われなければ、追加の接続は作成されません。これが、アプリケーションが実際に5つの接続をキューに入れる必要があるかどうかに関係なく、 create_engine()
がデフォルトでサイズ5の QueuePool
を使用することが完全に問題ない理由です。アプリケーションが実際に5つの接続を同時に使用した場合にのみ、プールはそのサイズに成長します。その場合、小さなプールの使用は完全に適切なデフォルト動作です。
Note
QueuePool
クラスは asyncioと互換性がありません 。 create_async_engine
を使用して AsyncEngine
のインスタンスを作成する場合、asyncio互換のキュー実装を利用する AsyncAdaptedQueuePool
クラスが代わりに使用されます。
Switching Pool Implementations¶
create_engine()
で別の種類のプールを使用する一般的な方法は、引数 poolclass
を使用することです。この引数は sqlalchemy.pool
モジュールからインポートされたクラスを受け入れ、プールの構築の詳細を処理します。ここでの一般的な使用例は、接続プーリングを無効にする場合で、これは NullPool
実装を使用して実現できます:
from sqlalchemy.pool import NullPool
engine = create_engine(
"postgresql+psycopg2://scott:tiger@localhost/test", poolclass=NullPool
)
Using a Custom Connection Function¶
さまざまな接続カスタマイズルーチンの詳細については Custom DBAPI connect() arguments / on-connect routines を参照してください。
Constructing a Pool¶
Pool
を単独で使用するには、必要な引数は creator
関数だけで、最初に渡され、その後に追加のオプションが続きます:
import sqlalchemy.pool as pool
import psycopg2
def getconn():
c = psycopg2.connect(user="ed", host="127.0.0.1", dbname="test")
return c
mypool = pool.QueuePool(getconn, max_overflow=10, pool_size=5)
次に、 Pool.connect()
関数を使用して、プールからDBAPI接続を取得できます。このメソッドの戻り値は、透過プロキシに含まれるDBAPI接続です:
# get a connection
conn = mypool.connect()
# use it
cursor_obj = conn.cursor()
cursor_obj.execute("select foo")
透過プロキシーの目的は、DBAPI接続が閉じられる代わりにプールに返されるように、 close()
呼び出しをインターセプトすることです。:
# "close" the connection. Returns
# it to the pool.
conn.close()
またプロキシーは、ガーベッジ・コレクションが行われたときに、含まれているDBAPI接続をプールに戻しますが、これがすぐに行われるかどうかはPythonでは確定的ではありません(cPythonでは一般的ですが)。ただし、この使用方法は推奨されておらず、特にasyncio DBAPIドライバではサポートされていません。
Reset On Return¶
このプールには、接続がプールに戻されたときにDBAPI接続の rollback()
メソッドを呼び出す”reset on return”動作が含まれています。これは、コミットされていないデータだけでなく、テーブル・ロックやロー・ロックも含めて、既存のトランザクション状態が接続から削除されるようにするためです。ほとんどのDBAPIでは、 rollback()
の呼び出しは安価であり、DBAPIがすでにトランザクションを完了している場合、このメソッドは何の操作も行わないはずです。
Disabling Reset on Return for non-transactional connections¶
autocommit 用に設定された接続を使用している場合や、MySQLのMyISAMエンジンのようなACID機能を持たないデータベースを使用している場合など、この rollback()
が役に立たない非常に特殊なケースでは、reset-on-returnの動作を無効にすることができます。これは通常、パフォーマンス上の理由から行われます。これは、 Pool
の Pool.reset_on_return
パラメータを使用することで影響を受ける可能性があります。このパラメータは create_engine()
から create_engine.pool_reset_on_return
としても利用でき、値``None``を渡します。これは以下の例で、 create_engine.isolation_level
パラメータ設定の``AUTOCOMMIT``と組み合わせて説明されています:
non_acid_engine = create_engine(
"mysql://scott:tiger@host/db",
pool_reset_on_return=None,
isolation_level="AUTOCOMMIT",
)
上記のエンジンは、接続がプールに戻されても実際にはROLLBACKを実行しません。AUTOCOMMITが有効になっているので、ドライバはBEGIN操作も実行しません。
Custom Reset-on-Return Schemes¶
単一の rollback()
で構成される reset on return
は、いくつかのユースケースでは十分ではないかもしれません。特に、テンポラリ・テーブルを使用するアプリケーションでは、これらのテーブルが接続のチェックイン時に自動的に削除されることを望む場合があります。一部の(ただし、すべてではありません)バックエンドには、データベース接続の範囲内でそのようなテーブルを リセット
できる機能が含まれています。これは、接続プールのリセットに望ましい動作です。準備された文のハンドルやサーバ側の文キャッシュなどの他のサーバリソースは、チェックインプロセスを超えて持続する場合があります。これは、詳細に応じて望ましい場合と望ましくない場合があります。ここでも、一部の(ただし、すべてではありません)バックエンドは、この状態をリセットする手段を提供する場合があります。このようなリセット方式を持つことが知られている2つのSQLAlchemyに含まれる方言には、Microsoft SQL Serverが含まれます。Microsoft SQL Serverでは、文書化されていないが広く知られている sp_reset_connection
というストアドプロシージャがよく使用されます。PostgreSQLでは、 DISCARD
RESET
DEALLOCATE
UNLISTEN
などの一連のコマンドが十分に文書化されています。
次の例は、 PoolEvents.reset()
イベントフックを使って、reset on returnをMicrosoft SQL Serverの sp_reset_connection
ストアドプロシージャに置き換える方法を示しています。 create_engine.pool_reset_on_return
パラメータは None
に設定されているので、カスタムスキームはデフォルトの動作を完全に置き換えることができます。カスタムフックの実装は、DBAPI自身のコミット/ロールバックの追跡がトランザクションの状態と一貫性を保つことが通常重要であるため、いかなる場合でも .rollback()
を呼び出します。:
from sqlalchemy import create_engine
from sqlalchemy import event
mssql_engine = create_engine(
"mssql+pyodbc://scott:tiger^5HHH@mssql2017:1433/test?driver=ODBC+Driver+17+for+SQL+Server",
# disable default reset-on-return scheme
pool_reset_on_return=None,
)
@event.listens_for(mssql_engine, "reset")
def _reset_mssql(dbapi_connection, connection_record, reset_state):
if not reset_state.terminate_only:
dbapi_connection.execute("{call sys.sp_reset_connection}")
# so that the DBAPI itself knows that the connection has been
# reset
dbapi_connection.rollback()
Changed in version 2.0.0b3: PoolEvents.reset()
イベントに状態引数を追加し、すべての”reset”発生に対してイベントが呼び出されるようにしました。これにより、カスタム”reset”ハンドラの場所として適切になります。 PoolEvents.checkin()
ハンドラを使用する以前のスキームも引き続き使用できます。
See also
Temporary Table / Resource Reset for Connection Pooling - in the Microsoft SQL Server documentation
Temporary Table / Resource Reset for Connection Pooling in the PostgreSQL documentation
Logging reset-on-return events¶
Re set on returnを含むプールイベントのロギングは、 logging.DEBUG
ログレベルを sqlalchemy.pool
ロガーと一緒に設定するか、 create_engine()
を使用するときに create_engine.echo_pool
を````”debug”`` に設定することで設定できます:
>>> from sqlalchemy import create_engine
>>> engine = create_engine("postgresql://scott:tiger@localhost/test", echo_pool="debug")
上記のプールは、終了時のリセットを含む詳細なログを表示します:
>>> c1 = engine.connect()
DEBUG sqlalchemy.pool.impl.QueuePool Created new connection <connection object ...>
DEBUG sqlalchemy.pool.impl.QueuePool Connection <connection object ...> checked out from pool
>>> c1.close()
DEBUG sqlalchemy.pool.impl.QueuePool Connection <connection object ...> being returned to pool
DEBUG sqlalchemy.pool.impl.QueuePool Connection <connection object ...> rollback-on-return
Pool Events¶
接続プールは、最初の接続時、新しい接続時、および接続のチェックアウトとチェックイン時にフックを実行できるようにするイベントインタフェースをサポートしています。詳細は PoolEvents
を参照してください。
Dealing with Disconnects¶
接続プールには、個々の接続およびその接続セット全体をリフレッシュする機能があり、以前にプールされた接続を”無効”として設定します。一般的な使用例は、データベース・サーバーが再起動され、以前に確立されたすべての接続が機能しなくなったときに、接続プールを正常にリカバリできるようにすることです。これには2つのアプローチがあります。
Disconnect Handling - Pessimistic¶
悲観的アプローチでは、各接続プール・チェックアウトの開始時にSQL接続に対してテスト・ステートメントを発行して、データベース接続がまだ有効であることをテストします。この実装は方言固有であり、DB API固有のpingメソッドを使用するか、”SELECT 1”のような単純なSQL文を使用して接続が有効かどうかをテストします。
この方法では、接続のチェックアウト・プロセスにわずかなオーバーヘッドが追加されますが、プールされた古い接続によるデータベース・エラーを完全に排除するための最も簡単で信頼性の高い方法です。呼び出し側アプリケーションは、プールからチェックアウトされた古い接続から回復できるように操作を編成する必要はありません。
チェックアウト時の接続の悲観的なテストは、 create_engine.pool_pre_ping
引数を介して create_engine()
から利用可能な Pool.pre_ping
引数を使用することで実現できます:
engine = create_engine("mysql+pymysql://user:pw@host/db", pool_pre_ping=True)
“事前ping”機能は、adBAPI固有の”ping”メソッドを呼び出すか、使用できない場合は”SELECT 1”と同等のSQLを出力してエラーをキャッチし、そのエラーを”切断”状態として検出することによって、方言ごとに動作します。ping/エラーチェックによって接続が使用できないと判断された場合、その接続はすぐにリサイクルされ、現在の時刻よりも古い他のすべてのプールされた接続は無効になるため、次にチェックアウトされるときにも使用前にリサイクルされます。
“pre ping”の実行時にデータベースがまだ使用できない場合、初期接続は失敗し、接続失敗のエラーが正常に伝達されます。データベースが接続に使用可能であるが、”ping”に応答できないというまれな状況では、”pre_ping”は、最後に受信したデータベース・エラーを伝播して、終了するまで最大3回試行します。
事前pingアプローチでは、 トランザクションやその他のSQL操作の途中で切断された接続に対応できないことに注意してください 。トランザクションの進行中にデータベースが使用できなくなると、トランザクションが失われ、データベースエラーが発生します。 Connection
オブジェクトが”切断”状態を検出し、接続をリサイクルし、この状態が発生したときに残りの接続プールを無効にしますが、例外が発生した個々の操作は失われ、操作を放棄するか、トランザクション全体を再試行するかはアプリケーション次第です。 Setting Transaction Isolation Levels including DBAPI Autocommit で説明されているように、エンジンがDB APIレベルのオートコミット接続を使用して設定されている場合、接続はイベントを使用して操作の途中で透過的に再接続される 可能性があります 。例については How Do I “Retry” a Statement Execution Automatically? を参照してください。
“SELECT 1”を使用し、切断を検出するためにエラーをキャッチするダイアレクトでは、 DialectEvents.handle_error()
フックを使用して、新しいバックエンド固有のエラーメッセージに対して切断テストを拡張することができます。
Custom / Legacy Pessimistic Ping¶
create_engine.pool_pre_ping
が追加される前は、歴史的に”pre-ping”アプローチは ConnectionEvents.engine_connect()
エンジンイベントを使用して手動で実行されていました。アプリケーションがすでにこのようなレシピを使用している場合、または特殊な動作が必要な場合の参考のために、最も一般的なレシピを以下に示します。:
from sqlalchemy import exc
from sqlalchemy import event
from sqlalchemy import select
some_engine = create_engine(...)
@event.listens_for(some_engine, "engine_connect")
def ping_connection(connection, branch):
if branch:
# this parameter is always False as of SQLAlchemy 2.0,
# but is still accepted by the event hook. In 1.x versions
# of SQLAlchemy, "branched" connections should be skipped.
return
try:
# run a SELECT 1. use a core select() so that
# the SELECT of a scalar value without a table is
# appropriately formatted for the backend
connection.scalar(select(1))
except exc.DBAPIError as err:
# catch SQLAlchemy's DBAPIError, which is a wrapper
# for the DBAPI's exception. It includes a .connection_invalidated
# attribute which specifies if this connection is a "disconnect"
# condition, which is based on inspection of the original exception
# by the dialect in use.
if err.connection_invalidated:
# run the same SELECT again - the connection will re-validate
# itself and establish a new connection. The disconnect detection
# here also causes the whole connection pool to be invalidated
# so that all stale connections are discarded.
connection.scalar(select(1))
else:
raise
上記のレシピには、”切断”状態を示すことがわかっているDBAPI例外を検出するためにSQLAlchemyの機能を利用しているという利点があります。また、この条件が発生したときに Engine
オブジェクトが現在の接続プールを正しく無効にし、現在の Connection
が新しいDBAPI接続を再有効化できるという利点もあります。
Disconnect Handling - Optimistic¶
悲観的処理が使用されていない場合や、トランザクション内で接続が使用されている途中でデータベースがシャットダウンまたは再起動された場合、古い/閉じられた接続を処理するもう1つの方法は、切断が発生したときにSQLAlchemyに切断を処理させることです。切断が発生すると、プール内のすべての接続が無効になります。つまり、切断は古いものと見なされ、次のチェックアウト時に更新されます。この動作は、 Pool
が Engine
と組み合わせて使用されることを前提としています。 Engine
には、切断イベントを検出してプールを自動的に更新するロジックがあります。
Connection
がDBAPI接続を使用しようとし、”切断”イベントに対応する例外が発生した場合、接続は無効になります。その後、 Connection
は Pool.recreate()
メソッドを呼び出し、現在チェックアウトされていないすべての接続を実質的に無効にして、次のチェックアウト時に新しい接続に置き換えられるようにします。この流れを以下のコード例で示します。:
from sqlalchemy import create_engine, exc
e = create_engine(...)
c = e.connect()
try:
# suppose the database has been restarted.
c.execute(text("SELECT * FROM table"))
c.close()
except exc.DBAPIError as e:
# an exception is raised, Connection is invalidated.
if e.connection_invalidated:
print("Connection was invalidated!")
# after the invalidate event, a new connection
# starts with a new Pool
c = e.connect()
c.execute(text("SELECT * FROM table"))
上記の例は、切断イベントが検出された後もプールを更新するために特別な介入が必要ないことを示しています。ただし、データベース使用不可イベントが発生している間に使用されている接続ごとに、1つのデータベース例外が発生します。ORMセッションを使用する一般的なWebアプリケーションでは、上記の条件は、500エラーで失敗した単一の要求に対応し、Webアプリケーションはそれを超えて正常に継続します。したがって、頻繁なデータベースの再起動が予想されないという点で、このアプローチは”楽観的”です。
Setting Pool Recycle¶
“楽観的”アプローチを補強する追加の設定は、プールのリサイクルパラメータを設定することです。このパラメータは、特定の経過時間を経過した特定の接続がプールで使用されないようにします。また、特定の期間が経過した古い接続を自動的に閉じるMySQLなどのデータベースバックエンドに適しています。:
from sqlalchemy import create_engine
e = create_engine("mysql+mysqldb://scott:tiger@localhost/test", pool_recycle=3600)
上記では、1時間以上開いていたDBAPI接続は、次回のチェックアウト時に無効にされ、置き換えられます。無効化はチェックアウト中に**のみ**発生し、チェックアウト状態に保持されている接続では発生しないことに注意してください。 pool_recycle
は Pool
自体の関数で、 Engine
が使用されているかどうかとは無関係です。
More on Invalidation¶
Pool
は、接続の明示的な無効化と、接続を使用不能にすると判断された条件に応じた自動的な無効化の両方を可能にする”接続無効化”サービスを提供します。
“無効化”とは、特定のDBAPI接続がプールから削除され、破棄されることを意味します。接続自体が閉じられない可能性があることが明確でない場合は、この接続で .close()
メソッドが呼び出されます。ただし、このメソッドが失敗した場合は、例外がログに記録されますが、操作は続行されます。
Engine
を使用する場合、 Connection.invalidate()
メソッドが明示的な無効化の通常のエントリポイントになります。DBAPI接続が無効化されるその他の条件には、次のものがあります。
OperationalError
のようなDBAPI例外は、connection.execute()
のようなメソッドが呼ばれた時に発生し、いわゆる”切断”状態を示すものとして検出されます。PythonのDBAPIは例外の性質を決定する標準システムを提供していないので、すべてのSQLAlchemyダイアレクトにはis_disconnect()
と呼ばれるシステムが含まれています。このシステムは、例外オブジェクトの内容を、文字列メッセージとそれに含まれる潜在的なエラーコードを含めて調べ、この例外が接続がもはや使用できないことを示しているかどうかを判断します。この場合、_ConnectionFairy.invalidate()
メソッドが呼び出され、DBAPI接続は破棄されます。
接続がプールに戻され、プールの”reset on return”動作によって指示されているように、
connection.rollback()
またはconnection.commit()
メソッドを呼び出すと、例外がスローされます。接続に対して最後にclose()
を呼び出そうとする試みが行われ、その後破棄されます。
PoolEvents.checkout()
を実装しているリスナがDisconnectError
例外を発生させた場合、これは接続が使用できなくなり、新しい接続を試みる必要があることを示します。
発生するすべての無効化は、 PoolEvents.invalidate()
イベントを呼び出します。
Supporting new database error codes for disconnect scenarios¶
SQLAlchemyの各ダイアレクトには、DBAPI例外が発生するたびに呼び出される is_disconnect()
というルーチンが含まれています。DBAPI例外オブジェクトがこのメソッドに渡され、ダイアレクト固有のヒューリスティックが、受け取ったエラーコードがデータベース接続が”切断された”ことを示しているのか、それとも再利用すべきであることを示す使用不能な状態にあることを示しているのかを判断します。ここで適用されるヒューリスティックは、 DialectEvents.handle_error()
イベントフックを使用してカスタマイズできます。これは通常、所有する Engine
オブジェクトを介して確立されます。このフックを使用すると、発生したすべてのエラーは ExceptionContext
と呼ばれるコンテキストオブジェクトを介して配信されます。カスタムイベントフックは、特定のエラーを”切断”状態と見なすかどうか、およびこの切断によって接続プール全体が切断されるかどうかを制御できます。
例えば、Oracleのエラーコード DPY-1001
と DPY-4011
を切断コードとして扱うサポートを追加するには、生成後にエンジンにイベントハンドラを適用します:
import re
from sqlalchemy import create_engine
engine = create_engine("oracle://scott:tiger@dnsname")
@event.listens_for(engine, "handle_error")
def handle_exception(context: ExceptionContext) -> None:
if not context.is_disconnect and re.match(
r"^(?:DPI-1001|DPI-4011)", str(context.original_exception)
):
context.is_disconnect = True
return None
上記のエラー処理関数は、発生したすべてのOracleエラーに対して呼び出されます。これには、切断エラー処理に依存するバックエンドに対して pool pre ping 機能を使用したときに検出されたエラーも含まれます(2.0の新機能)。
See also
Using FIFO vs. LIFO¶
QueuePool
クラスには QueuePool.use_lifo
というフラグがあります。これは create_engine()
から create_engine.pool_use_lifo
フラグを介してアクセスすることもできます。このフラグを 真
に設定すると、プールの”キュー”の動作が”スタック”の動作になります。例えば、プールに返される最後の接続は、次の要求で使用される最初の接続です。プール内の各接続を連続して使用するラウンドロビン効果を生み出す先入れ先出しのプールの長年の動作とは対照的に、lifoモードでは、過剰な接続をプール内でアイドル状態のままにし、サーバ側のタイムアウトスキームでこれらの接続を閉じることができます。FIFOとLIFOの違いは、基本的に、プールがアイドル状態の間でも接続の完全なセットを準備しておくことが望ましいかどうかということです。
engine = create_engine(“postgreql://”, pool_use_lifo=True, pool_pre_ping=True)
上記では create_engine.pool_pre_ping
フラグも使用していますので、サーバ側からクローズされたコネクションはコネクションプールによって自動的に処理され、新しいコネクションに置き換えられます。
このフラグは QueuePool
の使用にのみ適用されることに注意してください。
New in version 1.3.
See also
Using Connection Pools with Multiprocessing or os.fork()¶
接続プールを使用する場合、さらには create_engine()
によって作成された Engine
を使用する場合には、プールされた接続が 分岐したプロセスに共有されない ことが重要です。TCP接続はファイル記述子として表現され、通常はプロセスの境界を越えて動作します。つまり、完全に独立した2つ以上のPythonインタプリタ状態に代わって、ファイル記述子への同時アクセスが発生します。
ドライバやOSの仕様にもよりますが、ここで発生する問題は、動作しない接続から、複数のプロセスによって同時に使用されるソケット接続まで多岐にわたり、メッセージの破損につながります(後者のケースが一般的です)。
SQLAlchemy Engine
オブジェクトは、既存のデータベース接続の接続プールを参照します。そのため、このオブジェクトが子プロセスにレプリケートされるときの目的は、データベース接続が引き継がれないようにすることです。これには4つの一般的なアプローチがあります。
NullPool
を使ってプーリングを無効にします。これは、Engine
がどのコネクションも2回以上使わないようにする、最も単純なワンショットシステムです:from sqlalchemy.pool import NullPool engine = create_engine("mysql+mysqldb://user:pass@host/dbname", poolclass=NullPool)
任意の
Engine
でEngine.dispose()
を呼び出し、子プロセスの初期化フェーズでEngine.dispose.close
パラメータに`False`の値を渡します。これは、新しいプロセスが親プロセスの接続に接触せず、代わりに新しい接続から開始するようにするためです。 これは推奨されるアプローチですfrom multiprocessing import Pool engine = create_engine("mysql+mysqldb://user:pass@host/dbname") def run_in_process(some_data_record): with engine.connect() as conn: conn.execute(text("...")) def initializer(): """ensure the parent proc's database connections are not touched in the new connection pool""" engine.dispose(close=False) with Pool(10, initializer=initializer) as p: p.map(run_in_process, data)
New in version 1.4.33:
Engine.dispose.close
パラメータが追加されました。これにより、親プロセスが使用する接続に干渉することなく、子プロセス内の接続プールを置き換えることができます。
子プロセスが作成される 直前に
Engine.dispose()
を呼び出します。これにより、親接続が子プロセスに転送されないようにしながら、子プロセスが新しい接続プールで開始されます:engine = create_engine("mysql://user:pass@host/dbname") def run_in_process(): with engine.connect() as conn: conn.execute(text("...")) # before process starts, ensure engine.dispose() is called engine.dispose() p = Process(target=run_in_process) p.start()
プロセス境界を越えて共有されている接続をテストし、それらを無効にするイベントハンドラを接続プールに適用できます。:
from sqlalchemy import event from sqlalchemy import exc import os engine = create_engine("...") @event.listens_for(engine, "connect") def connect(dbapi_connection, connection_record): connection_record.info["pid"] = os.getpid() @event.listens_for(engine, "checkout") def checkout(dbapi_connection, connection_record, connection_proxy): pid = os.getpid() if connection_record.info["pid"] != pid: connection_record.dbapi_connection = connection_proxy.dbapi_connection = None raise exc.DisconnectionError( "Connection record belongs to pid %s, " "attempting to check out in pid %s" % (connection_record.info["pid"], pid) )
上記では、 Disconnect Handling - Pessimistic で説明されているのと同様のアプローチを使用して、別の親プロセスから発信されたDBAPI接続を “無効な” 接続として扱い、新しい接続を作成するために接続レコードをリサイクルするようプールに強制します。
上記の方法は、プロセス間で共有されている Engine
の場合に対応します。プロセス境界を越えて特定の Connection
を共有する場合には、上記の手順だけでは十分ではありません。特定の Connection
のスコープを単一のプロセス(およびスレッド)に対してローカルにしておきたいのです。さらに、トランザクションを開始し、アクティブな Connection
インスタンスを参照するanORM Session
オブジェクトのように、進行中のトランザクション状態をプロセス境界を越えて直接共有することもサポートされていません。ここでも、新しいプロセスで新しい Session
オブジェクトを作成したいのです。
Using a pool instance directly¶
プールの実装は、エンジンなしで直接使用できます。これは、他のSQLAlchemy機能なしでプールの動作を使用したいアプリケーションで使用できます。以下の例では、 create_pool_from_url()
を使用して、 MySQLdb
ダイアレクトのデフォルトのプールを取得しています:
from sqlalchemy import create_pool_from_url
my_pool = create_pool_from_url(
"mysql+mysqldb://", max_overflow=5, pool_size=5, pre_ping=True
)
con = my_pool.connect()
# use the connection
...
# then close it
con.close()
作成するプールのタイプが指定されていない場合は、デフォルトのものが使用されます。直接指定するには、次の例のように引数 poolclass
を使用します。:
from sqlalchemy import create_pool_from_url
from sqlalchemy import NullPool
my_pool = create_pool_from_url("mysql+mysqldb://", poolclass=NullPool)
API Documentation - Available Pool Implementations¶
Object Name | Description |
---|---|
Proxies a DBAPI connection and provides return-on-dereference support. |
|
Maintains a position in a connection pool which references a pooled connection. |
|
A |
|
An asyncio-compatible version of |
|
Interface for the object that maintains an individual database
connection on behalf of a |
|
Common base for the two connection-management interfaces
|
|
A Pool which does not pool connections. |
|
Abstract base class for connection pools. |
|
A connection-like adapter for a PEP 249 DBAPI connection, which
includes additional methods specific to the |
|
A |
|
A Pool that maintains one connection per thread. |
|
A Pool of exactly one connection, used for all requests. |
- class sqlalchemy.pool.Pool¶
Abstract base class for connection pools.
Members
Class signature
class
sqlalchemy.pool.Pool
(sqlalchemy.log.Identified
,sqlalchemy.event.registry.EventTarget
)-
method
sqlalchemy.pool.Pool.
__init__(creator: _CreatorFnType | _CreatorWRecFnType, recycle: int = -1, echo: log._EchoFlagType = None, logging_name: str | None = None, reset_on_return: _ResetStyleArgType = True, events: List[Tuple[_ListenerFnType, str]] | None = None, dialect: _ConnDialect | Dialect | None = None, pre_ping: bool = False, _dispatch: _DispatchCommon[Pool] | None = None)¶ Construct a Pool.
- Parameters:
creator¶ – a callable function that returns a DB-API connection object. The function will be called with parameters.
recycle¶ – If set to a value other than -1, number of seconds between connection recycling, which means upon checkout, if this timeout is surpassed the connection will be closed and replaced with a newly opened connection. Defaults to -1.
logging_name¶ – String identifier which will be used within the “name” field of logging records generated within the “sqlalchemy.pool” logger. Defaults to a hexstring of the object’s id.
echo¶ –
if True, the connection pool will log informational output such as when connections are invalidated as well as when connections are recycled to the default log handler, which defaults to
sys.stdout
for output.. If set to the string"debug"
, the logging will include pool checkouts and checkins.The
Pool.echo
parameter can also be set from thecreate_engine()
call by using thecreate_engine.echo_pool
parameter.See also
Configuring Logging - further detail on how to configure logging.
reset_on_return¶ –
Determine steps to take on connections as they are returned to the pool, which were not otherwise handled by a
Connection
. Available fromcreate_engine()
via thecreate_engine.pool_reset_on_return
parameter.Pool.reset_on_return
can have any of these values:"rollback"
- call rollback() on the connection, to release locks and transaction resources. This is the default value. The vast majority of use cases should leave this value set."commit"
- call commit() on the connection, to release locks and transaction resources. A commit here may be desirable for databases that cache query plans if a commit is emitted, such as Microsoft SQL Server. However, this value is more dangerous than ‘rollback’ because any data changes present on the transaction are committed unconditionally.None
- don’t do anything on the connection. This setting may be appropriate if the database / DBAPI works in pure “autocommit” mode at all times, or if a custom reset handler is established using thePoolEvents.reset()
event handler.True
- same as ‘rollback’, this is here for backwards compatibility.False
- same as None, this is here for backwards compatibility.
For further customization of reset on return, the
PoolEvents.reset()
event hook may be used which can perform any connection activity desired on reset.events¶ – a list of 2-tuples, each of the form
(callable, target)
which will be passed tolisten()
upon construction. Provided here so that event listeners can be assigned viacreate_engine()
before dialect-level listeners are applied.dialect¶ – a
Dialect
that will handle the job of calling rollback(), close(), or commit() on DBAPI connections. If omitted, a built-in “stub” dialect is used. Applications that make use ofcreate_engine()
should not use this parameter as it is handled by the engine creation strategy.pre_ping¶ –
if True, the pool will emit a “ping” (typically “SELECT 1”, but is dialect-specific) on the connection upon checkout, to test if the connection is alive or not. If not, the connection is transparently re-connected and upon success, all other pooled connections established prior to that timestamp are invalidated. Requires that a dialect is passed as well to interpret the disconnection error.
New in version 1.2.
-
method
sqlalchemy.pool.Pool.
connect() PoolProxiedConnection ¶ Return a DBAPI connection from the pool.
The connection is instrumented such that when its
close()
method is called, the connection will be returned to the pool.
-
method
sqlalchemy.pool.Pool.
dispose() None ¶ Dispose of this pool.
This method leaves the possibility of checked-out connections remaining open, as it only affects connections that are idle in the pool.
See also
-
method
- class sqlalchemy.pool.QueuePool¶
A
Pool
that imposes a limit on the number of open connections.QueuePool
is the default pooling implementation used for allEngine
objects other than SQLite with a:memory:
database.The
QueuePool
class is not compatible with asyncio andcreate_async_engine()
. TheAsyncAdaptedQueuePool
class is used automatically when usingcreate_async_engine()
, if no other kind of pool is specified.See also
Members
Class signature
-
method
sqlalchemy.pool.QueuePool.
__init__(creator: _CreatorFnType | _CreatorWRecFnType, pool_size: int = 5, max_overflow: int = 10, timeout: float = 30.0, use_lifo: bool = False, **kw: Any)¶ Construct a QueuePool.
- Parameters:
creator¶ – a callable function that returns a DB-API connection object, same as that of
Pool.creator
.pool_size¶ – The size of the pool to be maintained, defaults to 5. This is the largest number of connections that will be kept persistently in the pool. Note that the pool begins with no connections; once this number of connections is requested, that number of connections will remain.
pool_size
can be set to 0 to indicate no size limit; to disable pooling, use aNullPool
instead.max_overflow¶ – The maximum overflow size of the pool. When the number of checked-out connections reaches the size set in pool_size, additional connections will be returned up to this limit. When those additional connections are returned to the pool, they are disconnected and discarded. It follows then that the total number of simultaneous connections the pool will allow is pool_size + max_overflow, and the total number of “sleeping” connections the pool will allow is pool_size. max_overflow can be set to -1 to indicate no overflow limit; no limit will be placed on the total number of concurrent connections. Defaults to 10.
timeout¶ – The number of seconds to wait before giving up on returning a connection. Defaults to 30.0. This can be a float but is subject to the limitations of Python time functions which may not be reliable in the tens of milliseconds.
use_lifo¶ –
use LIFO (last-in-first-out) when retrieving connections instead of FIFO (first-in-first-out). Using LIFO, a server-side timeout scheme can reduce the number of connections used during non-peak periods of use. When planning for server-side timeouts, ensure that a recycle or pre-ping strategy is in use to gracefully handle stale connections.
New in version 1.3.
**kw¶ – Other keyword arguments including
Pool.recycle
,Pool.echo
,Pool.reset_on_return
and others are passed to thePool
constructor.
-
method
sqlalchemy.pool.QueuePool.
dispose() None ¶ Dispose of this pool.
This method leaves the possibility of checked-out connections remaining open, as it only affects connections that are idle in the pool.
See also
-
method
- class sqlalchemy.pool.AsyncAdaptedQueuePool¶
An asyncio-compatible version of
QueuePool
.This pool is used by default when using
AsyncEngine
engines that were generated fromcreate_async_engine()
. It uses an asyncio-compatible queue implementation that does not usethreading.Lock
.The arguments and operation of
AsyncAdaptedQueuePool
are otherwise identical to that ofQueuePool
.Class signature
class
sqlalchemy.pool.AsyncAdaptedQueuePool
(sqlalchemy.pool.impl.QueuePool
)
- class sqlalchemy.pool.SingletonThreadPool¶
A Pool that maintains one connection per thread.
Maintains one connection per each thread, never moving a connection to a thread other than the one which it was created in.
Warning
the
SingletonThreadPool
will call.close()
on arbitrary connections that exist beyond the size setting ofpool_size
, e.g. if more unique thread identities than whatpool_size
states are used. This cleanup is non-deterministic and not sensitive to whether or not the connections linked to those thread identities are currently in use.SingletonThreadPool
may be improved in a future release, however in its current status it is generally used only for test scenarios using a SQLite:memory:
database and is not recommended for production use.The
SingletonThreadPool
class is not compatible with asyncio andcreate_async_engine()
.Options are the same as those of
Pool
, as well as:- Parameters:
pool_size¶ – The number of threads in which to maintain connections at once. Defaults to five.
SingletonThreadPool
is used by the SQLite dialect automatically when a memory-based database is used. See SQLite.Members
Class signature
class
sqlalchemy.pool.SingletonThreadPool
(sqlalchemy.pool.base.Pool
)-
method
sqlalchemy.pool.SingletonThreadPool.
connect() PoolProxiedConnection ¶ Return a DBAPI connection from the pool.
The connection is instrumented such that when its
close()
method is called, the connection will be returned to the pool.
-
method
sqlalchemy.pool.SingletonThreadPool.
dispose() None ¶ Dispose of this pool.
-
method
sqlalchemy.pool.SingletonThreadPool.
recreate() SingletonThreadPool ¶ Return a new
Pool
, of the same class as this one and configured with identical creation arguments.This method is used in conjunction with
dispose()
to close out an entirePool
and create a new one in its place.
- class sqlalchemy.pool.AssertionPool¶
A
Pool
that allows at most one checked out connection at any given time.This will raise an exception if more than one connection is checked out at a time. Useful for debugging code that is using more connections than desired.
The
AssertionPool
class is compatible with asyncio andcreate_async_engine()
.Members
Class signature
class
sqlalchemy.pool.AssertionPool
(sqlalchemy.pool.base.Pool
)-
method
sqlalchemy.pool.AssertionPool.
dispose() None ¶ Dispose of this pool.
This method leaves the possibility of checked-out connections remaining open, as it only affects connections that are idle in the pool.
See also
-
method
sqlalchemy.pool.AssertionPool.
recreate() AssertionPool ¶ Return a new
Pool
, of the same class as this one and configured with identical creation arguments.This method is used in conjunction with
dispose()
to close out an entirePool
and create a new one in its place.
-
method
- class sqlalchemy.pool.NullPool¶
A Pool which does not pool connections.
Instead it literally opens and closes the underlying DB-API connection per each connection open/close.
Reconnect-related functions such as
recycle
and connection invalidation are not supported by this Pool implementation, since no connections are held persistently.The
NullPool
class is compatible with asyncio andcreate_async_engine()
.Members
Class signature
-
method
sqlalchemy.pool.NullPool.
dispose() None ¶ Dispose of this pool.
This method leaves the possibility of checked-out connections remaining open, as it only affects connections that are idle in the pool.
See also
-
method
- class sqlalchemy.pool.StaticPool¶
A Pool of exactly one connection, used for all requests.
Reconnect-related functions such as
recycle
and connection invalidation (which is also used to support auto-reconnect) are only partially supported right now and may not yield good results.The
StaticPool
class is compatible with asyncio andcreate_async_engine()
.Members
Class signature
class
sqlalchemy.pool.StaticPool
(sqlalchemy.pool.base.Pool
)-
method
sqlalchemy.pool.StaticPool.
dispose() None ¶ Dispose of this pool.
This method leaves the possibility of checked-out connections remaining open, as it only affects connections that are idle in the pool.
See also
-
method
sqlalchemy.pool.StaticPool.
recreate() StaticPool ¶ Return a new
Pool
, of the same class as this one and configured with identical creation arguments.This method is used in conjunction with
dispose()
to close out an entirePool
and create a new one in its place.
-
method
- class sqlalchemy.pool.ManagesConnection¶
Common base for the two connection-management interfaces
PoolProxiedConnection
andConnectionPoolEntry
.These two objects are typically exposed in the public facing API via the connection pool event hooks, documented at
PoolEvents
.Members
dbapi_connection, driver_connection, info, invalidate(), record_info
New in version 2.0.
-
attribute
sqlalchemy.pool.ManagesConnection.
dbapi_connection: DBAPIConnection | None¶ A reference to the actual DBAPI connection being tracked.
This is a PEP 249-compliant object that for traditional sync-style dialects is provided by the third-party DBAPI implementation in use. For asyncio dialects, the implementation is typically an adapter object provided by the SQLAlchemy dialect itself; the underlying asyncio object is available via the
ManagesConnection.driver_connection
attribute.SQLAlchemy’s interface for the DBAPI connection is based on the
DBAPIConnection
protocol object
-
attribute
sqlalchemy.pool.ManagesConnection.
driver_connection: Any | None¶ The “driver level” connection object as used by the Python DBAPI or database driver.
For traditional PEP 249 DBAPI implementations, this object will be the same object as that of
ManagesConnection.dbapi_connection
. For an asyncio database driver, this will be the ultimate “connection” object used by that driver, such as theasyncpg.Connection
object which will not have standard pep-249 methods.New in version 1.4.24.
-
attribute
sqlalchemy.pool.ManagesConnection.
info¶ Info dictionary associated with the underlying DBAPI connection referred to by this
ManagesConnection
instance, allowing user-defined data to be associated with the connection.The data in this dictionary is persistent for the lifespan of the DBAPI connection itself, including across pool checkins and checkouts. When the connection is invalidated and replaced with a new one, this dictionary is cleared.
For a
PoolProxiedConnection
instance that’s not associated with aConnectionPoolEntry
, such as if it were detached, the attribute returns a dictionary that is local to thatConnectionPoolEntry
. Therefore theManagesConnection.info
attribute will always provide a Python dictionary.See also
-
method
sqlalchemy.pool.ManagesConnection.
invalidate(e: BaseException | None = None, soft: bool = False) None ¶ Mark the managed connection as invalidated.
- Parameters:
See also
-
attribute
sqlalchemy.pool.ManagesConnection.
record_info¶ Persistent info dictionary associated with this
ManagesConnection
.Unlike the
ManagesConnection.info
dictionary, the lifespan of this dictionary is that of theConnectionPoolEntry
which owns it; therefore this dictionary will persist across reconnects and connection invalidation for a particular entry in the connection pool.For a
PoolProxiedConnection
instance that’s not associated with aConnectionPoolEntry
, such as if it were detached, the attribute returns None. Contrast to theManagesConnection.info
dictionary which is never None.See also
-
attribute
- class sqlalchemy.pool.ConnectionPoolEntry¶
Interface for the object that maintains an individual database connection on behalf of a
Pool
instance.The
ConnectionPoolEntry
object represents the long term maintainance of a particular connection for a pool, including expiring or invalidating that connection to have it replaced with a new one, which will continue to be maintained by that sameConnectionPoolEntry
instance. Compared toPoolProxiedConnection
, which is the short-term, per-checkout connection manager, this object lasts for the lifespan of a particular “slot” within a connection pool.The
ConnectionPoolEntry
object is mostly visible to public-facing API code when it is delivered to connection pool event hooks, such asPoolEvents.connect()
andPoolEvents.checkout()
.New in version 2.0:
ConnectionPoolEntry
provides the public facing interface for the_ConnectionRecord
internal class.Members
close(), dbapi_connection, driver_connection, in_use, info, invalidate(), record_info
Class signature
class
sqlalchemy.pool.ConnectionPoolEntry
(sqlalchemy.pool.base.ManagesConnection
)-
method
sqlalchemy.pool.ConnectionPoolEntry.
close() None ¶ Close the DBAPI connection managed by this connection pool entry.
-
attribute
sqlalchemy.pool.ConnectionPoolEntry.
dbapi_connection: DBAPIConnection | None¶ A reference to the actual DBAPI connection being tracked.
This is a PEP 249-compliant object that for traditional sync-style dialects is provided by the third-party DBAPI implementation in use. For asyncio dialects, the implementation is typically an adapter object provided by the SQLAlchemy dialect itself; the underlying asyncio object is available via the
ManagesConnection.driver_connection
attribute.SQLAlchemy’s interface for the DBAPI connection is based on the
DBAPIConnection
protocol object
-
attribute
sqlalchemy.pool.ConnectionPoolEntry.
driver_connection: Any | None¶ The “driver level” connection object as used by the Python DBAPI or database driver.
For traditional PEP 249 DBAPI implementations, this object will be the same object as that of
ManagesConnection.dbapi_connection
. For an asyncio database driver, this will be the ultimate “connection” object used by that driver, such as theasyncpg.Connection
object which will not have standard pep-249 methods.New in version 1.4.24.
-
attribute
sqlalchemy.pool.ConnectionPoolEntry.
in_use¶ Return True the connection is currently checked out
-
attribute
sqlalchemy.pool.ConnectionPoolEntry.
info¶ inherited from the
ManagesConnection.info
attribute ofManagesConnection
Info dictionary associated with the underlying DBAPI connection referred to by this
ManagesConnection
instance, allowing user-defined data to be associated with the connection.The data in this dictionary is persistent for the lifespan of the DBAPI connection itself, including across pool checkins and checkouts. When the connection is invalidated and replaced with a new one, this dictionary is cleared.
For a
PoolProxiedConnection
instance that’s not associated with aConnectionPoolEntry
, such as if it were detached, the attribute returns a dictionary that is local to thatConnectionPoolEntry
. Therefore theManagesConnection.info
attribute will always provide a Python dictionary.See also
-
method
sqlalchemy.pool.ConnectionPoolEntry.
invalidate(e: BaseException | None = None, soft: bool = False) None ¶ inherited from the
ManagesConnection.invalidate()
method ofManagesConnection
Mark the managed connection as invalidated.
- Parameters:
See also
-
attribute
sqlalchemy.pool.ConnectionPoolEntry.
record_info¶ inherited from the
ManagesConnection.record_info
attribute ofManagesConnection
Persistent info dictionary associated with this
ManagesConnection
.Unlike the
ManagesConnection.info
dictionary, the lifespan of this dictionary is that of theConnectionPoolEntry
which owns it; therefore this dictionary will persist across reconnects and connection invalidation for a particular entry in the connection pool.For a
PoolProxiedConnection
instance that’s not associated with aConnectionPoolEntry
, such as if it were detached, the attribute returns None. Contrast to theManagesConnection.info
dictionary which is never None.See also
-
method
- class sqlalchemy.pool.PoolProxiedConnection¶
A connection-like adapter for a PEP 249 DBAPI connection, which includes additional methods specific to the
Pool
implementation.PoolProxiedConnection
is the public-facing interface for the internal_ConnectionFairy
implementation object; users familiar with_ConnectionFairy
can consider this object to be equivalent.New in version 2.0:
PoolProxiedConnection
provides the public- facing interface for the_ConnectionFairy
internal class.Members
close(), dbapi_connection, detach(), driver_connection, info, invalidate(), is_detached, is_valid, record_info
Class signature
class
sqlalchemy.pool.PoolProxiedConnection
(sqlalchemy.pool.base.ManagesConnection
)-
method
sqlalchemy.pool.PoolProxiedConnection.
close() None ¶ Release this connection back to the pool.
The
PoolProxiedConnection.close()
method shadows the PEP 249.close()
method, altering its behavior to instead release the proxied connection back to the connection pool.Upon release to the pool, whether the connection stays “opened” and pooled in the Python process, versus actually closed out and removed from the Python process, is based on the pool implementation in use and its configuration and current state.
-
attribute
sqlalchemy.pool.PoolProxiedConnection.
dbapi_connection: DBAPIConnection | None¶ A reference to the actual DBAPI connection being tracked.
This is a PEP 249-compliant object that for traditional sync-style dialects is provided by the third-party DBAPI implementation in use. For asyncio dialects, the implementation is typically an adapter object provided by the SQLAlchemy dialect itself; the underlying asyncio object is available via the
ManagesConnection.driver_connection
attribute.SQLAlchemy’s interface for the DBAPI connection is based on the
DBAPIConnection
protocol object
-
method
sqlalchemy.pool.PoolProxiedConnection.
detach() None ¶ Separate this connection from its Pool.
This means that the connection will no longer be returned to the pool when closed, and will instead be literally closed. The associated
ConnectionPoolEntry
is de-associated from this DBAPI connection.Note that any overall connection limiting constraints imposed by a Pool implementation may be violated after a detach, as the detached connection is removed from the pool’s knowledge and control.
-
attribute
sqlalchemy.pool.PoolProxiedConnection.
driver_connection: Any | None¶ The “driver level” connection object as used by the Python DBAPI or database driver.
For traditional PEP 249 DBAPI implementations, this object will be the same object as that of
ManagesConnection.dbapi_connection
. For an asyncio database driver, this will be the ultimate “connection” object used by that driver, such as theasyncpg.Connection
object which will not have standard pep-249 methods.New in version 1.4.24.
-
attribute
sqlalchemy.pool.PoolProxiedConnection.
info¶ inherited from the
ManagesConnection.info
attribute ofManagesConnection
Info dictionary associated with the underlying DBAPI connection referred to by this
ManagesConnection
instance, allowing user-defined data to be associated with the connection.The data in this dictionary is persistent for the lifespan of the DBAPI connection itself, including across pool checkins and checkouts. When the connection is invalidated and replaced with a new one, this dictionary is cleared.
For a
PoolProxiedConnection
instance that’s not associated with aConnectionPoolEntry
, such as if it were detached, the attribute returns a dictionary that is local to thatConnectionPoolEntry
. Therefore theManagesConnection.info
attribute will always provide a Python dictionary.See also
-
method
sqlalchemy.pool.PoolProxiedConnection.
invalidate(e: BaseException | None = None, soft: bool = False) None ¶ inherited from the
ManagesConnection.invalidate()
method ofManagesConnection
Mark the managed connection as invalidated.
- Parameters:
See also
-
attribute
sqlalchemy.pool.PoolProxiedConnection.
is_detached¶ Return True if this
PoolProxiedConnection
is detached from its pool.
-
attribute
sqlalchemy.pool.PoolProxiedConnection.
is_valid¶ Return True if this
PoolProxiedConnection
still refers to an active DBAPI connection.
-
attribute
sqlalchemy.pool.PoolProxiedConnection.
record_info¶ inherited from the
ManagesConnection.record_info
attribute ofManagesConnection
Persistent info dictionary associated with this
ManagesConnection
.Unlike the
ManagesConnection.info
dictionary, the lifespan of this dictionary is that of theConnectionPoolEntry
which owns it; therefore this dictionary will persist across reconnects and connection invalidation for a particular entry in the connection pool.For a
PoolProxiedConnection
instance that’s not associated with aConnectionPoolEntry
, such as if it were detached, the attribute returns None. Contrast to theManagesConnection.info
dictionary which is never None.See also
-
method
- class sqlalchemy.pool._ConnectionFairy¶
Proxies a DBAPI connection and provides return-on-dereference support.
This is an internal object used by the
Pool
implementation to provide context management to a DBAPI connection delivered by thatPool
. The public facing interface for this class is described by thePoolProxiedConnection
class. See that class for public API details.The name “fairy” is inspired by the fact that the
_ConnectionFairy
object’s lifespan is transitory, as it lasts only for the length of a specific DBAPI connection being checked out from the pool, and additionally that as a transparent proxy, it is mostly invisible.Class signature
class
sqlalchemy.pool._ConnectionFairy
(sqlalchemy.pool.base.PoolProxiedConnection
)
- class sqlalchemy.pool._ConnectionRecord¶
Maintains a position in a connection pool which references a pooled connection.
This is an internal object used by the
Pool
implementation to provide context management to a DBAPI connection maintained by thatPool
. The public facing interface for this class is described by theConnectionPoolEntry
class. See that class for public API details.Class signature
class
sqlalchemy.pool._ConnectionRecord
(sqlalchemy.pool.base.ConnectionPoolEntry
)