今更理解するトランザクション

私は今までトランザクションを意図的に利用する機会が無く、「なんかDBの整合性を保つやつなんだよなー」くらいの理解度でした。他にもログを見ててBEGINCOMMITって何...?となっていたこともあり、トランザクション周りについて知る必要があったので、今まで知らなかったことを理解のためにまとめてみます。

トランザクションとは

PostgreSQL 16.4文書には以下のように書かれていました。

トランザクションの基本的要点は複数の手順を単一の「全てか無しか」の操作にまとめ上げることです。 手順の進行途中の状態は他の同時実行中のトランザクションからは見えません。 トランザクションの完結の障害となる何らかのエラーが起こると、それらの手順はどれもデータベースにまったく影響を与えません。

https://www.postgresql.jp/document/16/html/tutorial-transactions.html より

以下が要点だと認識しています。

  • DBの変更内容を一括で反映する or 反映しない 仕組み
  • 他の同時実行中のトランザクションからは見えない(※実際には設定によって左右される認識)

と言うことで、整合性を保つと言うのは誤りではないものの、より具体的に概念が理解できました。

どうやってトランザクションを実行するのか

PostgreSQLの場合、以下のようにBEGIN~COMMITで囲むことで実行できます。

BEGIN;
-- 実行したい処理
COMMIT;

実際にどうなるのか試してみた

ターミナルを2つ準備して試してみます。 以下リポジトリを利用して、dbshell上でコマンドを実行します。

https://github.com/nibuno/djangoTaskApp

また、トランザクション分離レベルはデフォルトのREAD COMMITTEDで実施しています。

ターミナル1

postgres=# BEGIN;
BEGIN
postgres=*# INSERT INTO task (title, content, status, "order", created_user_id, limit_date, updated_user_id, created_at, updated_at)
VALUES ('Sample Task', 'This is a sample content.', 0, 1, 1, '2024-12-31', 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
INSERT 0 1

ここで、ターミナル2を開いてSample Taskを検索してみます。

ターミナル2

postgres=# select * from task where title = 'Sample Task';
 id | content | created_at | updated_at | created_user_id | updated_user_id | title | limit_date | status | order 
----+---------+------------+------------+-----------------+-----------------+-------+------------+--------+-------
(0 rows)

この段階では、まだ結果が表示されません。

ここでターミナル1でCOMMITしてみます。

postgres=*# COMMIT;
COMMIT

その後、改めてターミナル2でSELECT文を実行してみると以下のようになっていました。

postgres=# select * from task where title = 'Sample Task';
 id |          content          |          created_at           |          updated_at           | created_user_id | updated_user_id |    title    |
 limit_date | status | order 
----+---------------------------+-------------------------------+-------------------------------+-----------------+-----------------+-------------+
------------+--------+-------
 37 | This is a sample content. | 2024-11-10 01:33:55.430143+00 | 2024-11-10 01:33:55.430143+00 |               1 |               1 | Sample Task |
 2024-12-31 |      0 |     1
(1 row)

という方法で、登録結果が確認できました。