Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

2PL(ツーピーエル)とは | 意味や読み方など丁寧でわかりやすい用語解説

2PL(ツーピーエル)の意味や読み方など、初心者にもわかりやすいように丁寧に解説しています。

作成日: 更新日:

読み方

日本語表記

ツーピーエル (ツーピーエル)

英語表記

2PL (ツーピーエル)

用語解説

「2PL」とは、Two-Phase Locking(二相ロック)の略称であり、データベースシステムにおいて複数のトランザクションが同時に動作する際の整合性を保つための並行性制御プロトコルの一つである。システムエンジニアにとって、データベースがどのようにデータの整合性を維持しているかを理解することは非常に重要であり、2PLはその基盤となる技術の一つである。

まず、データベースにおける並行性制御が必要な理由について簡単に説明する。現代のデータベースシステムでは、多数のユーザーやアプリケーションが同時にデータを読み書きするのが一般的である。例えば、銀行システムで複数の顧客が同時に自分の口座から送金したり、残高を照会したりする場合、これら一連の操作はそれぞれ独立したトランザクションとして実行される。もし、これらのトランザクションが何の制御もなく自由にデータにアクセスした場合、あるトランザクションがデータの更新途中に別のトランザクションがそのデータを読み取ってしまい、不正確な結果を得たり、データの破壊が発生したりする可能性がある。このような問題を「並行性問題」と呼ぶ。データベースは、ACID特性と呼ばれる4つの重要な特性(原子性、一貫性、分離性、永続性)を保証することで、データの信頼性を維持する。このうち、「分離性(Isolation)」は、複数のトランザクションが同時に実行されても、あたかも一つずつ直列に実行されたかのように見えることを保証するものであり、2PLはこの分離性を実現するための主要なメカニズムの一つである。

2PLは、トランザクションがデータ項目にアクセスする際に「ロック」と呼ばれる排他制御機構を利用する。ロックとは、特定のデータ項目が現在どのトランザクションによってどのような目的で利用されているかを示す標識のようなものであり、他のトランザクションのアクセスを一時的に制限することでデータの整合性を守る。2PLの最大の特徴は、このロックの獲得と解放を「二つのフェーズ」に厳密に分けて行う点にある。

第一のフェーズは「成長フェーズ(Growing Phase)」と呼ばれる。このフェーズでは、トランザクションがデータの読み書きに必要なすべてのロックを獲得していく。トランザクションは、参照したいデータ項目に対して「共有ロック(Shared Lock、Sロック)」を、更新したいデータ項目に対して「排他ロック(Exclusive Lock、Xロック)」を要求する。共有ロックは、複数のトランザクションが同時に同じデータ項目に対して獲得できるロックであり、主にデータ参照のために用いられる。一方、排他ロックは、一度に一つのトランザクションしか獲得できないロックであり、データの更新や書き込みのために用いられる。成長フェーズ中、トランザクションは必要なロックを順次獲得していくが、このフェーズでは一度獲得したロックを解放することはできない。つまり、トランザクションはロックを獲得し続ける一方であり、ロックの数は増える一方である。

第二のフェーズは「縮小フェーズ(Shrinking Phase)」と呼ばれる。このフェーズに入ると、トランザクションは成長フェーズで獲得したロックを順次解放していく。このフェーズでは、新たにロックを獲得することは一切できない。つまり、一度でもロックを解放し始めたトランザクションは、それ以降、新たなロックを要求することは許されない。トランザクションは、必要な処理を完了し、不要になったロックから順に解放していき、最終的にはすべてのロックを解放して終了する。

なぜこのような二つのフェーズに分けることが、分離性を保証するために重要なのか。それは、トランザクションがデータの整合性を崩す可能性のある「中途半端な状態」でロックを解放することを防ぐためである。もし、成長フェーズと縮小フェーズの区別がなく、トランザクションがいつでもロックの獲得と解放を自由に行える場合、あるトランザクションが重要な更新作業の途中でロックを一時的に解放してしまい、その間に別のトランザクションがその未確定のデータを参照・更新してしまう可能性がある。これは「ダーティリード(Dirty Read)」や「ノンリピータブルリード(Non-repeatable Read)」、あるいは「ファントムリード(Phantom Read)」といった並行性問題を引き起こす。2PLでは、トランザクションが全てのロックを獲得し終えてからでないとロックの解放を開始できないため、他のトランザクションが未確定のデータにアクセスする機会を最小限に抑えることができる。これにより、各トランザクションが直列に実行されたかのような状態、すなわち「直列化可能性(Serializability)」が保証され、データの整合性が維持される。

しかし、2PLにも課題が存在する。最大の課題の一つは「デッドロック(Deadlock)」である。これは、複数のトランザクションが互いに相手が保持しているロックの解放を待ち続ける状態であり、どのトランザクションも処理を進められなくなる状況を指す。例えば、トランザクションAがデータXのロックを持ち、データYのロックを待っている間に、トランザクションBがデータYのロックを持ち、データXのロックを待つといった状況が典型的である。このようなデッドロックを検出・解決するためのメカニズム(デッドロック検出、タイムアウトなど)がデータベースシステムには必要となる。また、厳密なロック制御は、システムの並行性を低下させる可能性もある。多くのロックを獲得し、それを長く保持すると、他のトランザクションがロックの解放を待つ時間が長くなり、全体のスループットが低下することがある。

2PLは、その基本的な考え方から派生した多くのバリエーション(例えば、Strict 2PL、Strong 2PLなど)とともに、現代のリレーショナルデータベースシステムにおいて広く採用されている並行性制御プロトコルである。システムエンジニアを目指す者として、この基本的なロックメカニズムとその働きを理解することは、データベースシステムの設計、チューニング、および問題解決において非常に役立つ基礎知識となる。

関連コンテンツ