新しいPostgreSQLクラスタ

2010年10月26日(火)

4. トランザクションの一貫性保証と、Postgres-XCの構造

上記の例でも、クラスタ全体を一つのデータベースとして扱うには不十分です。「2. 書き込みスケール・アウトの難しさ」で説明したように、各データベースにおいてトランザクションの実行順序をそろえることができないので、クラスタを構成する各データベースの内容を正しく維持できないからです。

Postgres-XCでは、GTM(Global Transaction Manager)と呼ぶ機能を使って、この問題を克服しています。

GTMの説明をする前に、ベースとなるPostgreSQLにおいて、トランザクションの実行処理がどのように制御されているのか、簡単に説明します。

PostgreSQLでは、すべてのトランザクションに「通し番号」(Transaction ID、XID)が付けられます。これにより、トランザクションの開始順が分かります。実際には、トランザクションの中のSQL文で書き出したデータは、トランザクションが完了した時点で、ほかのトランザクションからも見えるようになります。完了以前では見えません。なぜなら、書き出す内容が、さらに変更される場合があるからです。

この模様を、図5に示します。「トランザクション1」は、「a」を書き換え、次いで「b」を追加します。この時点ではまだ、ほかのトランザクション「トランザクション2」には、見えません。トランザクション1が処理を完了した時点で、トランザクション2からも、これらの書き込み結果が見えるようになります*1

  • [*1] これは、トランザクション2が「Read Committed」と呼ぶ隔離レベルの場合です。ほかに「Serializable」と呼ぶ隔離レベルがあり、この場合は、トランザクション2が完了するまで、トランザクション1の書き換え結果は見えません。

図5: データベースへの書き出しと、ほかのトランザクションの関係


このように、PostgreSQLでは(ほかのデータベースでもそうですが)、データベースへの書き込み処理が行われてから、その結果がほかのトランザクションに見えるようになるまでに、時間差があります。その間にも、多くのトランザクションが問題なく並列実行できるように、PostgreSQLでは「MVCC」(Multi-Version Concurrency Control)と呼ぶ機構を使っています。

MVCCは、簡単に言うと「データベースへの書き出し結果は、ほかのトランザクションには見えず、その1つ前の状態が見える」ということです。図6に、少し具体的に示します*2。トランザクション1が実行中の場合、ほかのトランザクション(この場合はトランザクション2)は、書き出し前の情報が見えます。こうすることで、2つのトランザクションが並列に実行できるのです。

  • [*2] これも、トランザクション2の隔離レベルが「Serializable」の場合です。

図6: MVCCを使った時の、書き込みデータの見え方


このように、各トランザクションに応じたデータベースの状態を正しく見せるようにするため、PostgreSQLでは、スナップショットと呼ぶ情報を内部的に使っています。これは、簡単に言えば、実行中のトランザクション(つまり、トランザクションID)のリストです*3

  • [*3] 厳密にはこれ以外の情報も含まれますが、今回は簡単のため、割愛します。

トランザクションIDとスナップショットの管理を、個別のデータベースでバラバラに行うのではなく、1カ所にまとめて管理し、各データベースに供給します。これにより、複数のデータベースが集まっても、相互間で一貫したトランザクション管理ができます。

Postgres-XCでは、この部分(トランザクションIDとスナップショットの管理)を、構成要素のデータベースから切り離し、GTM(Global Transaction Manager)として実装しました。

GTMで管理されるトランザクションは、グローバル・トランザクションと呼びます。グローバル・トランザクションのIDは、グローバル・トランザクションID(GXID)と呼び、グローバル・トランザクションのスナップショットは、グローバル・スナップショット(g-snapshot)と呼びます。

Postgres-XCでは、さらに、図4に示したように、SQLの解析と実行を、それぞれ異なる構成要素で実行させることにしました。

SQLの解析はCoordinatorと呼ぶ構成要素が、SQLの実行はData Nodeと呼ぶ構成要素が担当します。CoordinatorとData Node中のすべてのトランザクションは、GTMによって番号を割り当ててもらい、スナップショットを供給してもらって実行します。Coordinatorで解析したSQLをData Nodeに送る場合は、解析したときに使ったGXIDとg-snapshotも一緒に送ります。

GTMとCoordinator、Data Nodeで構成されるPostgres-XCの概要図を、図7に示します。Data Nodeは、異なるCooridnatorから送られるトランザクションを処理しますが、使用するGXIDやg-snapshotは、Postgres-XC全体が単独のPostgreSQLと同じ原理で管理されているので、データに矛盾が生じることはありません。

図7: Postgres-XCの構成


GTMの実装は、独自のものです。しかし、CoordinatorもData Nodeも、PostgreSQLを元に、これを拡張する形で実装しています。アプリケーションとPostgres-XCとのインタフェースは、PostgreSQLのものと同一です。

5. そのほかのGTMの役割

PostgreSQLでは、データベース全体で値を管理する必要があるものがあります。この中でも重要なのが、シーケンスとタイム・スタンプです。

シーケンスは、例えば「1から順に数字を割り振る」といった機能を提供するものです。これを、各データベースでばらばらに採番すると、重複した値が割り当てられる可能性があります。こういったことのないよう、シーケンスの値は、GTMが割り当ているようにしています。

同様に、タイム・スタンプの値も、各データベースごとにバラバラでは困ります。このため、GTMが値を割り当てるようにしています。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています