このコースではトランザクションについて3回取り上げるよ。毎回新しい発見があるはず。今回はトランザクションの基本を学ぼう。コース後半ではトランザクションの分離レベルについて、最後にはネストしたトランザクションの細かい動きも見ていくよ。
トランザクションとは
まずはシンプルに定義から。トランザクションとは、一緒に実行されるべきアクションのグループのこと。 それだけ。
ここから大事なポイントがある:もしグループ内のどれか(どれでも!)のアクションで失敗したら、他のすべてのアクションの結果も元に戻して、システムを最初の状態に戻さなきゃいけない。
SQLの観点だと、トランザクションは(例えば挿入、更新、削除などの)アクションのセットで、トランザクション内のすべての操作が成功するか、どれも実行されないかのどちらかを保証してくれる。これによってデータベース操作が信頼できて一貫性のあるものになるんだ。特に決済処理や関連データの更新みたいなクリティカルな場面で超大事!
例えば、2つの銀行口座間でお金を送金する場合を考えてみて。シンプルにすると、2つの連続した操作がある:
- 1つの口座から金額を引き落とす。
- もう1つの口座に同じ金額を入金する。
もし操作の最後で失敗したら(例えばサーバーが落ちたとか)、どちらのユーザーも損しないことが大事。つまり、両方のステップが成功(トランザクションが確定)するか、両方とも元に戻す(トランザクションがキャンセル)か、どっちかだよ。
トランザクションとACID原則
トランザクションはACID原則に基づいてる。これは4つの大事な特徴を思い出させてくれる:
- Atomicity(アトミック性): 全部やるか、全部やらないか。トランザクション内のすべての操作が実行されるか、全部元に戻る。
- Consistency(一貫性): トランザクションの前後でデータは正しい状態を保つ。
- Isolation(分離性): それぞれのトランザクションは、まるで自分だけがシステムで動いてるみたいに扱われる。
- Durability(永続性): コミットした後は、サーバーが落ちてもデータはちゃんと残る。
トランザクションを操作する基本コマンド
じゃあ実践の準備!トランザクションを操作する3つのメインコマンドを紹介するね:
BEGIN
新しいトランザクションを開始する。以降の操作はこの中で実行される。COMMIT
変更を確定する。このコマンドを実行すると、すべての操作が永続的になる。ROLLBACK
変更を取り消す。何か問題があったらトランザクションを元に戻して、データは最初の状態に戻る。
トランザクションの基本構文
トランザクションのシンプルな構造:
BEGIN;
-- ここに自分のSQL操作を書く
COMMIT;
ROLLBACKの使い方例:
BEGIN;
-- studentsテーブルの変更
UPDATE students
SET grade = grade + 10
WHERE id = 1;
-- おっと!これはミスだったと気づいた。
ROLLBACK;
実際の課題でのトランザクション利用例
例えば、こんなテーブルがあるとしよう:
students:
| id | name | grade |
|---|---|---|
| 1 | Otto Lin | 85 |
| 2 | Anna Song | 90 |
courses:
| course_id | course_name |
|---|---|
| 1 | 数学 |
| 2 | 歴史 |
例えば、学生をコースに登録しつつ、平均点も同時に更新したい場合:
BEGIN;
-- ステップ1: "コース登録"テーブルにレコードを追加
INSERT INTO course_enrollments (student_id, course_id)
VALUES (1, 2);
-- ステップ2: 学生の平均点を更新
UPDATE students
SET grade = grade + 5
WHERE id = 1;
COMMIT;
もしサーバーが1つ目と2つ目の間で落ちたらどうなる?トランザクションを使わなかったら、コース登録だけ追加されて平均点は更新されない、みたいな一貫性のない状態になる。でもトランザクションを使えば、両方とも成功するか、両方ともキャンセルされる。
トランザクション内でのエラー処理
たまに何かうまくいかなくて、ちゃんとエラーを処理したい時がある。PostgreSQLではエラーが起きたら自動的にトランザクションがロールバックされるよ。
わざとミスしてみて、どうなるか見てみよう。例えばcourse_enrollmentsテーブルのstudent_idカラムにユニーク制約があるとする。重複した行を追加しようとしてみよう:
BEGIN;
INSERT INTO course_enrollments (student_id, course_id)
VALUES (1, 2);
-- トランザクション終了(まだ実行してない)
COMMIT;
すでにコースに登録されている学生を追加しようとするとエラーになって、PostgreSQLは自動的にトランザクションをロールバックしてくれる。
ROLLBACKで手動ロールバック
エラーは予測できないことも多いから、何かおかしいと思ったら自分でトランザクションをロールバックしたくなるよね:
BEGIN;
-- 新しい学生を追加
INSERT INTO students (name, grade)
VALUES ('Omori Sanny', 75);
-- おっと!間違えて学生を追加しちゃった。
ROLLBACK;
ROLLBACKコマンドの後はテーブルは変わらないまま — Omori Sannyはstudentsに現れない。
便利なヒントとよくあるミス
トランザクションを使うときは、いくつかの大事なルールを覚えておくと楽になるよ:
- 複数ステップの操作、特に複数テーブルを変更する場合は必ずトランザクションを使おう。
- 変更を確定するのを忘れないで(
COMMIT)。忘れるとトランザクションが未完了のままで、データが変わらないよ。 - 複雑な操作はトランザクションでラップしてデータの一貫性を守ろう。
- どこかでエラーが出たら、
ROLLBACKを使うのを恐れないで。
これでトランザクションで操作をコントロールする方法がわかったね。あとは実際に使って、データの整合性を守るトランザクションをもっと学んでいこう!
GO TO FULL VERSION