
【RDS for PostgreSQL】idle_in_transaction_session_timeout で切断されたとき、未コミットの INSERT がどうなるか確認してみた
アプリケーションの不具合などで、トランザクションを開始したまま放置された接続(idle in transaction)が残ることがあります。
idle_in_transaction_session_timeout を設定すると、こうした接続をサーバー側で自動で切断できますが、切断されたときに「トランザクション内の変更はどうなるのか」「クライアントにはどう見えるのか」は、設定前に把握しておきたいところです。
本記事では、RDS for PostgreSQL で未コミットの INSERT を作ってタイムアウトまで放置し、切断時の挙動を確認します。
実施環境
- RDS for PostgreSQL 17.10
- RDS と同じ VPC にある EC2(AL2023) から psql クライアントで接続
※ EC2 に PostgreSQL を入れる方法は以下記事を参照
やってみた
まず検証用のテーブルを作り、実験前の idle_in_transaction_session_timeout の設定値を確認します。(86400000 ms = 24 h)
-- テーブル作成
postgres=> CREATE TABLE t_idle (id int);
CREATE TABLE
-- パラメータ確認
postgres=> SELECT name, setting, unit, source
FROM pg_settings
WHERE name = 'idle_in_transaction_session_timeout';
name | setting | unit | source
-------------------------------------+----------+------+--------------------
idle_in_transaction_session_timeout | 86400000 | ms | configuration file
(1 row)
-- 当該パラメータは現在 1d(=1日) に設定されている
postgres=> SHOW idle_in_transaction_session_timeout;
idle_in_transaction_session_timeout
-------------------------------------
1d
(1 row)
このセッションだけ 10秒でタイムアウトするようにパラメータを設定します。
postgres=> SET idle_in_transaction_session_timeout = '10s';
SET
postgres=> SHOW idle_in_transaction_session_timeout;
idle_in_transaction_session_timeout
-------------------------------------
10s
(1 row)
トランザクションを開始して INSERT し、COMMIT せずに10秒以上放置します。
-- トランザクション開始前のテーブルの状態を確認
-- 現在は空の状態
postgres=> SELECT * FROM t_idle;
id
----
(0 rows)
-- トランザクション開始
postgres=> BEGIN;
BEGIN
-- 値を挿入
postgres=*> INSERT INTO t_idle VALUES (1);
INSERT 0 1
-- テーブルの中身を確認
-- 値が挿入されている
postgres=*> SELECT * FROM t_idle;
id
----
1
(1 row)
postgres=*>
前述の状態から、10 秒以上経過しても上記 psql の画面に変化はありません。
再度 SELECT を実行してみましょう。
postgres=*> SELECT * FROM t_idle;
FATAL: terminating connection due to idle-in-transaction timeout
SSL connection has been closed unexpectedly
The connection to the server was lost. Attempting reset: Succeeded.
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off, ALPN: postgresql)
postgres=>
今度はエラーが出て、サーバーから接続を切断されました。
idle_in_transaction_session_timeout を超えても psql の画面は変わりませんが、次のクエリを実行したタイミングでセッション終了に気づくという形になりました。
また、切断時のメッセージは terminating connection due to idle-in-transaction timeout でした。
その後、psql が自動で再接続した(Attempting reset: Succeeded.)ため、そのまま入力を続けられます。
再接続後の状態を確認した結果、テーブルの中身は 0 件で、未コミットだった INSERT は接続の切断に伴ってロールバックされていることがわかります。
また SET で変更した値は 1d に戻っています。SET はセッション単位の設定なので、再接続によって新しいセッションになったことが分かります。
-- テーブルの中身は 0 件のまま
postgres=> SELECT * FROM t_idle;
id
----
(0 rows)
postgres=> SHOW idle_in_transaction_session_timeout;
idle_in_transaction_session_timeout
-------------------------------------
1d
(1 row)
終わりに
idle_in_transaction_session_timeout を超えると、サーバーが接続を切断し、トランザクション内の未コミットの INSERT はロールバックされることを確認できました。
タイムアウトを過ぎても psql の画面はすぐには変わらず、次のクエリを実行したタイミングで切断に気づく点にも注意が必要です。
切断すると未コミットの変更は失われるため、実際に運用で設定する際は、アプリケーション側の挙動も含めて事前に確認しておくことをおすすめします。
本記事がどなたかのお役に立てば幸いです。
参考情報






