🗂

[PostgreSQL] トランザクションをコミットせずにコネクションが切れた場合の挙動

2023/06/18に公開

はじめに

アプリケーションの実装不備等で、ロールバックがされないまま DB との接続が切れたらどうなるんだ、と思って調べてみました。PostgreSQL の公式ドキュメントを探してみても明示的な記載はがなさそうだったため、記事に残しておくことにしました。

結論

PostgreSQL ではデータベースとの接続を切ると終了していないトランザクションはロールバックされるようです。

検証

検証してみます。使用した PostgreSQL のバージョンは 14.8 です。

psqlpostgres データベースに接続します。

$ psql -h localhost -p 5432 -U postgres -d postgres
psql (14.8 (Homebrew), server 14.6 (Debian 14.6-1.pgdg110+1))
Type "help" for help.

テーブルを作ってトランザクションを開始し、該当テーブルにレコードを INSERT してみます。

postgres=# CREATE TABLE users (
  id serial NOT NULL,
  name varchar(255) NOT NULL,
  PRIMARY KEY(id)
);
postgres=# START TRANSACTION;
postgres=*# INSERT INTO users (name) VALUES ('user1'), ('user2'), ('user3');
postgres=*# SELECT * FROM users;
 id | name
----+-------
  1 | user1
  2 | user2
  3 | user3

トランザクションを終了せずに psql の接続を切ります。

postgres=#
\q

もう一度データベースに接続して、レコードを取得してみると INSERT されていないことが確認できます。

postgres=# select * from users;
 id | name
----+------
(0 rows)

今回クライアントには psql を使いましたが、使っている DB クライアントやドライバによっては接続の終了前に自動的にトランザクションをコミットする可能性があります。トランザクション途中の変更を意図せず永続化させないようにするには、接続を閉じる前は常に明示的にトランザクションをロールバックしておくようにすると良いかもしれません。

補足

正直ロールバックして当たり前でしょ、と感じていたのですが、DBMS によっては同じ挙動をしないようです。例えば Oracle DB のドキュメントには以下のような記載がありました。

トランザクションは、次のいずれかの状況が発生すると終了します。

  • ...
  • ユーザーが Oracle Database の接続を切断する場合。カレント・トランザクションはコミットされます。

https://docs.oracle.com/cd/E15817_01/server.111/e05765/transact.htm

自分は Oracle を使ったことがなかったので全然知りませんでした。

参考

http://server-helper.doorblog.jp/archives/5686942.html

GitHubで編集を提案

Discussion