1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Aurora DSQLでコネクションプールはできるのか?(psycopg2編)

Posted at

はじめに

Aurora DSQLについて、とあるJAWSでの登壇を聞いたり、認証トークン・最大接続時間の仕様を確認したりしてみたのですが、ふとコネクションプーリングとかできるのかな?と思い、検証してみた記事です。

今回はPythonで確認してみました。

認証トークンについて

Aurora DSQLは、時限式トークンを作成し、これをパスワードとして、DSQLへの接続を行います。

つまり、永続的にパスワードを固定にすることができません。

なお、DSQLはPostgreSQL互換であるため、PostgreSQL用のライブラリpsycopg2で接続可能です。

class DSQLConnector:
    @contextmanager
    def connect(self, cluster_identifier, token, database='postgres', username='admin'):
        connection = None
        try:
            connection = psycopg2.connect(
                host=cluster_identifier,
                database=database,
                user=username,
+                password=token, # 認証トークン
                port=5432,
                sslmode='require'
            )
            yield connection
            
        except psycopg2.Error as e:
            logger.error(f"データベース接続エラー: {e}")
            raise
        finally:
            if connection:
                connection.close()

また、DBeaverのようなPostgreSQLに対応したクライアントであれば、PostgreSQLのように接続可能です。

有効期限

認証トークンはデフォルトで15分(900秒)、最大1週間(604,800秒)の間で有効期限を設定できます。

1週間を超えるトークン発行の動作確認するとX-Amz-Expires must be less than a week (in seconds)のエラーが出ました。

connection to server at "g4abult6r6rrzachxrubfgunia.dsql.ap-northeast-1.on.aws" (2406:da14:1713:ba05:e526:ffb6:3622:ba1), port 5432 failed: FATAL:  unable to accept connection, access denied
DETAIL:  Session Id: gjtes4nzjgrmtph2ufucbti6gy
HINT:  X-Amz-Expires must be less than a week (in seconds)

最大接続時間

下記ページを見ると、Maximum connection duration60 minutesとあります。

この60分制限は、認証トークンの有効期限とは関係なく、設定変更できない固定値の模様です。

試しに120秒有効な認証トークンを取得後、1分間隔でSELECT 1;を投入するプログラムで検証してみました。

こんな感じにログが出力されていき、

2025-09-08 05:28:46.590 - 8736956608 - MainThread - __main__ - INFO - ✓ DB接続成功 - カウント: 1
2025-09-08 05:29:46.619 - 8736956608 - MainThread - __main__ - INFO - ✓ DB接続成功 - カウント: 2

最終的に1時間周辺でエラーSSL SYSCALL error: EOF detectedが出力されていることを確認しました。

2025-09-08 06:30:48.193 - 8736956608 - MainThread - __main__ - INFO - ✓ DB接続成功 - カウント: 63
2025-09-08 06:31:48.214 - 8736956608 - MainThread - __main__ - INFO - ✓ DB接続成功 - カウント: 64
2025-09-08 06:32:48.239 - 8736956608 - MainThread - __main__ - INFO - ✓ DB接続成功 - カウント: 65
2025-09-08 06:33:48.263 - 8736956608 - MainThread - __main__ - INFO - ✓ DB接続成功 - カウント: 66
2025-09-08 06:34:48.274 - 8736956608 - MainThread - __main__ - ERROR - データベース接続エラー: SSL SYSCALL error: EOF detected

最大トランザクション時間

次にトランザクションの時間です。

先ほどのページには、Maximum transaction time5 minutesとあるのですが、これがどうしても再現できませんでした...

ThreadedConnectionPoolを使ったコネクションプーリング

こういった時限式のパスワードや、短い接続時間といった制約がある中で、コネクションプーリングができるのかを検証してみます。

種別  変更可否
Authentication Token(認証トークン) 15分 可能(最大1週間)
Maximum Connection Duration(最大接続時間) 60分 不可
Maximum Transaction Time(最大トランザクション時間) 5分 不可

最初にpsycopg2にはThreadedConnectionPoolというコネクションプーリングの機構があるので、これを使ってコネクションプーリングができるかを試してみました。

結果、以下の2点から実現出来ませんでした。
プールを全て作成し直すことで、実現はできるのですが、コネクションプーリングの意味が半減してしまいそうです。

原因1:新たなコネクションを作成する際のパスワードを更新できない

ThreadedConnectionPoolは最初に以下のようなソースでコネクションプーリングを指定します。

ここで認証トークンをパスワードとして指定しますが、以降、新たなコネクションを作成する際は、この認証トークンを使い続けることになり、認証トークンの有効期限切れ以降は新たなコネクションが作れなくなります。

なお、有効期限を超えたトークンを利用しようとすると、接続時に以下のエラーが返ってきます。

ERROR:__main__:✗ DB接続エラー: connection to server at "g4abult6r6rrzachxrubfgunia.dsql.ap-northeast-1.on.aws" (2406:da14:1713:ba03:1755:b00b:6b7c:39c7), port 5432 failed: FATAL:  unable to accept connection, access denied
DETAIL:  Session Id: tztetkom2iixzdlke7qpmzfgbi
HINT:  Signature expired: 20250908T000805Z is now earlier than 20250908T000830Z (20250908T000835Z - 0 min.)

原因2:自前で作ったコネクションをコネクションプールに戻すことができない

自前で新たな認証トークンを作成した上でコネクションを作成し、プールに戻せばいいのでは?と考え試してみたのですが、管理外のコネクションをプールに入れようとすると、trying to put unkeyed connectionのエラーが出て、格納できませんでした。

自前でコネクションプーリングをしてみる。

ThreadedConnectionPoolが使えないのなら...ということで、自分で作ってみました。

以下ソースです。

1時間経過すると、SSL SYSCALL error: EOF detectedのエラーでコネクションが死んでしまいますが、ここで新たな認証トークンを取得し、コネクションを作成、そしてプールに戻すことでコネクションプーリングが実現できています。

2025-09-08 05:50:49.729 - 6177730560 - Thread-1 (worker_thread) - __main__ - WARNING - 接続健全性チェック失敗: SSL SYSCALL error: EOF detected

2025-09-08 05:50:49.729 - 6177730560 - Thread-1 (worker_thread) - __main__ - WARNING - 不健全な接続を検出、破棄して新しい接続を作成
2025-09-08 05:50:49.982 - 6177730560 - Thread-1 (worker_thread) - __main__ - INFO - 新しい接続を作成して返却: conn_4335794352
2025-09-08 05:50:50.133 - 6177730560 - Thread-1 (worker_thread) - __main__ - INFO - ✓ スレッド1: thread_1 at 2025-09-07 20:50:50.008245+00:00
2025-09-08 05:50:50.133 - 6177730560 - Thread-1 (worker_thread) - __main__ - INFO - プール状態 (スレッド1): 総接続数:3, 利用可能:3, 使用中:0

ただ、1時間の制限関係なく、不定期に以下のようなエラーも発生することがありました。
こちら原因不明です。

2025-09-08 04:46:46.693 - 6177730560 - Thread-1 (worker_thread) - __main__ - WARNING - 接続健全性チェック失敗: server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.

そもそもDSQLにコネクションプーリングは必要なのか?

最後にコネクションプーリングがそもそもDSQLにも必要なのかを少し考えてみました。

コネクションプーリングを利用するメリットの一つとして、パフォーマンスの向上があります。

DBへの接続は時間とリソースを消費するので、プールから既存の接続を再利用することで、毎回新しい接続を作成する必要がなくなり、アプリケーションの応答速度が大幅に改善されます。

では、DSQLの場合は、どれくらいの効果があるかを見てみました。

先ほどのSSL SYSCALL error: EOF detectedを検出してから、コネクションを再作成し、SQLを投入する処理の時間は、404msでした。

2025-09-08 05:50:49.729 - 6177730560 - Thread-1 (worker_thread) - __main__ - WARNING - 不健全な接続を検出、破棄して新しい接続を作成
2025-09-08 05:50:49.982 - 6177730560 - Thread-1 (worker_thread) - __main__ - INFO - 新しい接続を作成して返却: conn_4335794352
2025-09-08 05:50:50.133 - 6177730560 - Thread-1 (worker_thread) - __main__ - INFO - ✓ スレッド1: thread_1 at 2025-09-07 20:50:50.008245+00:00
2025-09-08 05:50:50.133 - 6177730560 - Thread-1 (worker_thread) - __main__ - INFO - プール状態 (スレッド1): 総接続数:3, 利用可能:3, 使用中:0

一方でコネクションプーリングが有効な場合、18ミリ秒となり、22倍くらい速い結果になりました。

2025-09-08 05:54:50.663 - 6177730560 - Thread-1 (worker_thread) - __main__ - INFO - プールから健全な接続を取得: conn_4335793344
2025-09-08 05:54:50.681 - 6177730560 - Thread-1 (worker_thread) - __main__ - INFO - ✓ スレッド1: thread_1 at 2025-09-07 20:48:49.596725+00:00
2025-09-08 05:54:50.681 - 6177730560 - Thread-1 (worker_thread) - __main__ - INFO - プール状態 (スレッド1): 総接続数:3, 利用可能:3, 使用中:0

普通のDBと比べ、認証トークンの作成処理もあるため、DSQLこそコネクションプーリングを使うべきかもです。

まとめ

ということで、コネクションプーリングがDSQLでも有効かつ、出来ることがわかりました。

psycopg2ThreadedConnectionPoolを使ったコネクションプーリングでは実現できず、今回は自前で作ってしましたが、以下のページを見ると、SQLAlchemyでも出来そうなので、次の記事で検証してみます!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?