PgBouncerトランザクションレベルプーリングのためにSQLAlchemyで接続プーリングを最適に使用する方法は?


15

SQLAlchemyを使用して、トランザクションレベルのプーリングを使用して、PgBouncerの背後にあるPostgreSQLデータベースを照会します。

この種のセットアップに使用する最適なパターンは何ですか?を使用してプロセスごとに1つのエンジンを使用するConnectionPool必要がありますか、または要求ごとにエンジンを作成し、NullPoolそれらのそれぞれに使用する必要がありますか?使用する必要がある別のパターンはありますか?

どうもありがとう!さらに情報が必要な場合はお知らせください。できるだけ早く更新します。

回答:


9

PGBouncerを使用すると、おそらくNullPoolだけを使いたくなるでしょう。その場合、サブプロセスの境界を越えてソケット接続が行われないため、サブプロセス間で単一のエンジンを共有できる場合があります。ただし、この境界を越えて、アクティブなトランザクションを持つセッションなど、Connectionオブジェクトを参照するものを共有することはできません。ただし、「リクエストごとのエンジン」は絶対にしたくないでしょう。エンジンは、特定のデータベースURLに関する多くの情報を初めて見たときに蓄積する高価なオブジェクトです。


4

アプリケーション名を設定する

多くのプロセスを実行する予定の場合は、それらの接続元を知る必要があります。PGBouncerはこれをに非表示にしpg_stat_activityます。application_name必要な情報を慎重に設定してこれを解決します。

# Sets the application name for this connection in the form of
#   application-name:user@host
prog = os.path.basename(sys.argv[0]) or 'desjob'
username = pwd.getpwuid (os.getuid ()).pw_name
hostname = socket.gethostname().split(".")[0
args.setdefault('connect_args', {'application_name': "%s:%s@%s" %
    (prog, username, hostname)})
args.setdefault('isolation_level', "AUTOCOMMIT")
engine = create_engine(url, **args)

セッションを優先

Engineオブジェクトからのリクエストは、複数の接続を生成して保持できるため、セッションを使用します。Postgresへの接続はそれほど高価ではありませんが、PGBouncerを使用すればさらに安価です。NullPoolPostgresに表示される接続が実際に使用されている接続のみになるように、常に使用します。

from sqlalchemy.pool import Pool, NullPool
engine = create_engine(uri, poolclass=NullPool)

アイドルトランザクションを排除する

PGBouncerを使用してスケーリングすることが目的の場合、トランザクションが開いたままになるのを避けることが不可欠です。これを行うには、有効autocommit する必要があります。これはSQLAlchemyでは簡単ではありません...「オートコミット」と呼ばれるものを設定できる場所は3つあります。

psycopg2自動コミット

conn = psycopg2.connect(uri)
conn.autocommit = True

SQLAlchemyはその下で何が起こっているのかを知る必要があるため、安全でないと推定されます。

セッション自動コミット

Session = sessionmaker(bind=engine, autocommit=True)
session = Session()

これには、慎重で明示的な処理が必要です。

session.begin()
session.execute(...)
session.rollback()

関数呼び出しと例外処理は非常に困難でbegin()あり、commit()ネストできないため です。

def A():
  session.begin()
  ...
  session.rollback()

def B():
  session.begin()
  try:
      A() # error, already open

このモードでは、psycopg2 autocommitFalse(デフォルト)のように見えます。

エンジンの自動コミット

エンジンの"AUTOCOMMIT"作成時にエンジン分離モードを設定すると、既存のコードを変更する必要のない新しいデフォルトの動作が確立されます。

engine = create_engine(uri, isolation_level="AUTOCOMMIT")

このモードでは、psycopg2 autocommitTrue

ここでの主要な問題は、コードのブロックがトランザクションでラップされることを保証する唯一の方法が、ステートメントを手動で発行することであることです。

session.execute("BEGIN")
#...
session.execute("COMMIT")
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.