ITの教科書検索
入門読了 約10分

トランザクションとACID特性とは ― 排他制御の基本

トランザクションは、複数の処理をまとめて、すべて反映するか全部取り消すかのどちらかにする仕組みです。ACID特性の4つの性質と、排他制御・ロックの基本、障害回復が分かります。

目次
  1. トランザクションとは
  2. 排他制御とロックの仕組み
  3. ACID特性の4つの考え方
  4. コミットとロールバック
  5. 障害回復の基本
  6. 練習問題

トランザクションとは、複数の処理をまとめて1つの単位にしたもの

トランザクションとは、データベースへの複数の処理をまとめて、1つの単位として扱う仕組みです。単位の中の処理は、すべて反映されるか、すべて取り消されるかのどちらかになります。一部だけ反映された状態にはなりません。

例えば、口座Aから口座Bへ送金する処理を考えます。口座Aから1万円を引く処理と、口座Bに1万円を足す処理の、2つのSQL文が必要です。この2つを1つのトランザクションにまとめておけば、途中で故障が起きても、両方取り消されます。

口座Aから引く処理だけが反映されると、1万円がどこにも存在しない状態になります。DBMSは、この矛盾を防ぐ機能を持っています。その中心になるのが、排他制御とACID特性です。

排他制御(同時実行制御)とは、同時更新による矛盾を防ぐ仕組み

排他制御とは、複数のトランザクションが同時に同じデータを更新しても、矛盾が起きないようにする仕組みです。同時実行制御と呼ぶこともあります。代表的なやり方が、ロック方式です。

ロックとは、あるトランザクションが使っているデータに付けて、他のトランザクションの操作を制限する印です。ロックが許可されないとき、後から来たトランザクションは、先にロックを取った側の処理が終わるまで待たされます。

ロックが無い場合注文アプリ在庫管理アプリ在庫を読む在庫 = 101減らして書く在庫 = 9在庫を読む在庫 = 101減らして書く在庫 = 9ロックがある場合注文アプリ在庫管理アプリ専有ロックを取り読む在庫 = 101減らして書く在庫 = 9ロックを放すロックを待つロックを待つロックを待つ専有ロックを取り読む在庫 = 91減らして書く在庫 = 8
左はロックが無い場合です。両方が在庫=10を読んでから書き込むため、更新が1回分消えます(在庫=9のまま)。右はロックがある場合です。先に読んだ側が専有ロックを取り、もう一方は解放されるまで待つため、2回分の更新が両方反映されます(在庫=8)。

ロックが無いと、両方のプログラムが古い在庫数を読んでから書き込むので、片方の更新が消えてしまいます。ロックがあれば、先に読んだ側の処理が終わるまで、もう片方は待たされます。その結果、2回分の更新が両方反映されます。

ロックには、データを読むだけのときに使う共有ロックと、データを書き換えるときに使う専有ロックがあります。共有ロックは、他の共有ロックと同時に許可されます。専有ロックは、他のどのロックとも同時には許可されません。

共有ロックと専有ロックの違い
種類許可される組み合わせ向く場面
共有ロック他の共有ロックとは同時に許可されるデータを読むだけの処理
専有ロック他のどのロックとも同時に許可されないデータを書き換える処理

図の在庫の例では、読んだ値をもとに書き換えるので、読む時点から専有ロックを取ります。共有ロックでは、もう片方も同時に在庫を読めてしまうためです。読む時点で先にロックを取るこのやり方と、ロックを取らずに更新の時点で衝突を見つけるやり方の違いは、楽観ロックと悲観ロックの記事で比べています。

ロックを取る範囲の大きさを、ロック粒度と呼びます。表全体をロックすると他の処理を長く待たせますが、管理は簡単です。行単位でロックすると待たせる範囲は狭くなりますが、管理する情報が増えます。

複数のトランザクションが互いのロックの解放を待ち合い、どちらも先に進めなくなることがあります。この状態をデッドロックと呼びます。デッドロックが起きる仕組みと検知後の対処は、排他制御とデッドロックの記事で詳しく説明します。

ACID特性とは、トランザクションに求められる4つの性質

ACID特性とは、トランザクション処理に求められる4つの性質です。原子性・一貫性・独立性・永続性の4つを指します。複数の利用者が同時にデータベースにアクセスしても、データを矛盾させないために必要です。

4つの性質は、互いに支え合っています。独立性は、主にロックなどの仕組みで支えられます。独立性をどこまで厳しく守るかは、分離レベルという段階で選べます。原子性と永続性は、次に説明するコミットとロールバック、そしてログの仕組みで支えられます。

コミットとロールバックが、原子性と永続性を支える

コミットとは、トランザクションの中の変更を、データベースに確定させる操作です。コミットが終わると、その変更は失われません。これが、永続性にあたります。

ロールバックとは、トランザクションの中の変更を取り消す操作です。そのトランザクションが行った変更は、すべて取り消されます。表の変更をきっかけに動くトリガが行った変更も、同じトランザクションに含まれるので一緒に取り消されます。コミットとロールバックのどちらかで終わる点が、原子性にあたります。WHEREを付け忘れたDELETE文をROLLBACKで取り消す例は、INSERT・UPDATE・DELETE文の記事で見られます。

トランザクションが保持していたロックは、コミットまたはロールバックが終わると解放されます。ロックが解放されるまで、他のトランザクションは待たされたままです。PostgreSQLでは、WITH HOLDを付けずに開いたカーソルも、このとき閉じられます。データベースが複数のサイトに分かれているとき、全サイトでコミットをそろえる仕組みは分散データベースの記事で説明しています。

障害回復とは、バックアップとログで矛盾のない状態に戻す仕組み

障害回復とは、停電や機器の故障が起きても、矛盾のない状態にデータベースを戻す仕組みです。障害に備えるバックアップの方式と、故障後に元に戻すリカバリ処理の2つに分かれます。

DBMSは、データを書き換えるたびに、その内容をジャーナルファイル(ログファイル)に記録しています。故障が起きたとき、このログをもとに、障害発生直前の状態まで戻します。

ディスクの故障などでデータが失われた場合は、まずバックアップからデータを戻します。そのうえで、コミットされた変更をログから再現します。この処理を、ロールフォワード(フォワードリカバリ)と呼びます。

コミットされていなかった変更をログから取り消す処理を、ロールバック(バックワードリカバリ)と呼びます。この2つを使い分けて、矛盾のない状態に戻します。障害の種類やチェックポイントの位置で、どちらを使うかを決める手順は、ロールフォワードとロールバックの記事で説明しています。戻す元になるバックアップの取り方は、フル・差分・増分バックアップの記事で比べています。

参考にした資料

練習問題(全5問)

Q1トランザクションの説明として最も適切なものはどれ?
Q2ACID特性のうち、コミットが終わるまで途中の変更が他のトランザクションから見えない性質はどれ?
Q32つのプログラムが同じ在庫データを同時に読み書きするとき、ロックが無い場合に起きることとして正しいものはどれ?
Q4専有ロックの説明として正しいものはどれ?
Q5障害回復のために、データの変更内容を記録しておくファイルを何と呼ぶ?

選んでから「採点する」を押すと、解説つきで答え合わせができます。

関連記事

おすすめの本 PR

セキュリティとデータベースは、基本情報技術者試験の対策本でまとめて学べます。

目的別の本の選び方を見る

データベースの記事を続けて読む

データベース 全36本中27本目