【実務・中級編】 トランザクション分離レベル – PostgreSQL

「またデータベースのロックでハマったのか?」

そうぼやきたくなる気持ち、よく分かります。PostgreSQLを触り始めると誰もが一度は通る道、それが「トランザクション分離レベル」です。

教科書を読めば「ダーティリードがどうの」「非再現読み取りがどうの」と小難しい言葉が並んでいますが、実際の現場で大切なのは「どのレベルを選べば、自分の書いたコードが安全に、かつパフォーマンスを落とさずに動くか」という一点に尽きます。

今日は、現場で後輩に教えるつもりで、この「分離レベル」の正体を紐解いていきましょう。

—

なぜ「分離レベル」という概念が必要なのか

まず前提として、データベースは「複数のユーザーが同時に同じデータを触る」場所です。もし、全員が勝手に書き込みを始めたら、データは一瞬で壊れますよね。

そこで、トランザクションという単位で処理を隔離するわけですが、「隔離を厳しくすれば安全だけど遅くなる」「隔離を緩くすれば速いけど危ない」というトレードオフが生まれます。この「どこまで隔離するか」を決めるのが分離レベルです。

まずは、PostgreSQLでよく耳にする3つのレベルを整理しましょう。

—

1. Read Committed(デフォルトの安心感)

PostgreSQLのデフォルト設定です。「コミットされたデータだけが見える」という、直感的で一番使いやすいレベルです。

  • 防げる現象: ダーティリード(コミット前の他人のゴミデータを見ない)
  • 許容する現象: 非再現読み取り(同じクエリを2回打つと、途中で誰かに書き換えられて結果が変わる)

どんな時に使う?

基本はこれだけでOKです。「同じトランザクション内で、同じ行を2回参照した時に値が変わっていても困らない」ような処理なら、迷わずこれでいきましょう。

— トランザクションA
BEGIN;
SELECT balance FROM accounts WHERE id = 1; — 1000円
— (この間に他人が1000円を2000円に更新してコミット)
SELECT balance FROM accounts WHERE id = 1; — 2000円になってしまう!
COMMIT;

—

2. Repeatable Read(一貫性の守護者)

「同じトランザクション内なら、いつ何度読んでも同じ結果を返す」という約束です。

  • 防げる現象: ダーティリード、非再現読み取り
  • 許容する現象: 直列化異常(※ただしPostgreSQLは賢いので、もし競合があればエラーを返して止めてくれます)

どんな時に使う?

「集計処理」や「整合性が厳密に求められるレポート作成」などで重宝します。トランザクション開始時のスナップショットで固定されるので、途中で他人がデータを書き換えても、自分には影響が及びません。

注意点: 誰かが先に書き換えた行を自分が更新しようとすると、「could not serialize access」というエラーが出ます。これを食らったら、「アプリケーション側でリトライ処理を書く」のが定石です。

—

3. Serializable(最強の盾)

「複数のトランザクションを、まるで順番に1つずつ実行したかのように」振る舞わせる、最強のレベルです。

  • 防げる現象: すべての不整合
  • メリット: 考えることがない。絶対安全。
  • デメリット: パフォーマンスが落ちるし、競合時のリトライが頻発する。

どんな時に使う?

「絶対にミスが許されない金融系の勘定処理」など、特殊な要件以外ではあまり使いません。現場で「とりあえずSerializableにしておけば安心だろ」と考えるのは、パフォーマンス地獄への入り口です。まずは上の2つで解決できないか検討するのが、プロの仕事です。

—

結局、現場ではどう判断すべき?

僕の経験則を伝えておきますね。

1. 基本は `Read Committed`: これで十分。ほとんどのWebアプリはこれで動いています。
2. 同じトランザクション内で複数回読み取り、かつ矛盾が困るなら `Repeatable Read`: ただし、エラーが起きた時のリトライロジックを必ずセットで実装すること。
3. `Serializable` は最終手段: どうしても競合を制御しきれない、複雑な整合性チェックが必要な時だけ。

「どの分離レベルにするか」という問いは、実は「その処理の整合性を、どこまでアプリケーション(コード)側でカバーできるか」という問いでもあります。

データベースを「魔法の箱」だと思わず、賢く使いこなすこと。そうすれば、深夜のデータ不整合対応に怯えることもなくなるはずです。

さて、そろそろ次のタスクに行きましょうか。何か詰まったら、いつでも聞いてくださいね。

コメント

タイトルとURLをコピーしました