分散データベースと2相コミットとは ― 同期の仕組み
分散
分散データベースとは、複数のサイトのデータを1つのデータベースとして使う仕組み
分散データベースとは、ネットワークでつないだ複数のサイトにデータを置き、利用者からは1つのデータベースとして使えるようにしたものです。拠点ごとにサーバを置くシステムや、クラウドで複数の場所にデータを複製する構成で使います。サイトをまたぐ更新を、すべてのサイトでそろえて確定させる方式が、2相コミットメントです。
ここでのサイトとは、データベースを動かすサーバが置かれた場所のことです。例えば、東京の本社と大阪の支社に1台ずつデータベースがあり、両方のデータをまとめて扱う場面を考えます。コミットやロックの基本は、トランザクションとACID特性と排他制御とデッドロックの記事で説明しています。
分散データベースは、サイトごとに独立して動けるが、データをそろえる仕組みが必要
分散データベースでは、各サイトのデータベースを、それぞれ独立して管理します。そのため、1つのサイトが故障しても、ほかのサイトの処理まで止まるとは限りません。故障したサイトの復旧も、ほかのサイトとは別に進められます。1台のサーバに頼らない構成の別の形として、端末どうしが直接データを送り合うP2Pもあります。
一方で、サイトをまたぐ処理には注意が必要です。1つのトランザクションが2つのサイトのデータを更新するとき、片方だけ確定すると、データが食い違います。同じデータを複数のサイトに持つ場合は、変更をほかのサイトへ送って、内容をそろえ続ける必要もあります。
分散データベースの留意点は、サイトの間でデータをそろえる仕組みが必要なことです。その仕組みが、後で説明するレプリケーションと2相コミットメントです。
透過性とは、データの置き場所を意識せずに使える性質
分散データベースの利用者は、どの表がどのサイトにあるかを知らなくても、同じSQLで問い合わせられます。データが分かれていることを利用者に意識させないこの性質を、透過性と呼びます。透過性の目的は、分散データベースを1つのデータベースのように見せることです。
例えば、顧客表が大阪のサイトにあっても、東京の利用者は手元の表と同じ書き方で読めます。置き場所を意識しなくてよいので、管理者が表を別のサイトへ移しても、アプリケーションを書き換えずに済みます。トランザクションも、サイトが1つのときと同じCOMMITやROLLBACKで扱えます。
レプリケーションとは、同じデータを複数のサイトに複製する仕組み
レプリケーションとは、あるサイトのデータを、別のサイトに複製する仕組みです。複製を持つサイトは、元のサイトの変更を受け取って、同じ内容に保ちます。元のサイトが使えなくなっても、複製を持つサイトでデータを使い続けられます。
データを複数のサイトに置くやり方は、複製のほかにもう1つあります。表を地域ごとなどに分けて、各サイトが別のデータを持つやり方です。同じ3つのサイトで、2つの置き方を比べます。
複製では、東京での変更を大阪と福岡へ送ります。同じデータが3か所にあるので、1か所が止まっても読めますが、変更を送り続ける手間がかかります。分割では、各サイトが自分の地域の顧客だけを持つため、変更を送り合いません。代わりに、全地域の顧客をまとめて見るときは、3つのサイトに問い合わせることになります。
キーの値でデータを分けて複数の台に置く作りは、NoSQLの多くの製品が台数を増やすときに使っています。その仕組みはNoSQLの記事で説明しています。管理者を置かず、参加者どうしで同じ記録を持ち合う仕組みは、ブロックチェーンの記事にまとめました。
レプリケーションには、同期と非同期がある
複製へ変更を送るタイミングには、2つの方式があります。同期の方式では、すべてのサーバでコミットが終わるまで、その更新を確定したとみなしません。そのため、元のサーバが故障して複製に切り替えても、確定したデータは失われません。
非同期の方式では、コミットのあと、少し遅れて変更を複製へ送ります。元のサーバで確定してから複製に届くまでに、時間の差ができます。その間に故障して切り替えると、届いていなかった更新が失われることがあります。複製から読むと、少し古い内容が返ることもあります。
非同期の方式は、同期では遅すぎる場合に使います。AWSのデータベースサービスにも、同期で複製するマルチAZ配置と、非同期で複製するリードレプリカがあります。2つの違いはAmazon RDSの記事で比べています。Amazon Auroraは、書き込んだデータを、3つのAZにある6つのストレージノードへ同期で複製します。
2相コミットメントは、全サイトの準備を確かめてから一斉にコミットする
2つのサイトにまたがる振替を考えます。サイト1にある口座Aから1万円を引き、サイト2にある口座Bに1万円を足します。この2つの更新は、1つのトランザクションとして、両方確定するか両方取り消すかのどちらかにしなければなりません。
複数のサイトでコミットをそろえる仕組みを、コミットメント制御と呼びます。まず、問い合わせをせずに、いきなり全サイトへ「コミットせよ」と指示するやり方を考えます。このやり方だと、指示が届く前に1つのサイトが故障したとき、そのサイトの更新だけが取り消されます。
2相コミットメントは、コミットの前に、全サイトがコミットできる状態かを確かめる方式です。取りまとめ役のサイトを、主サイトと呼びます。主サイトは、次の2つの段階で全体を進めます。
第1相では、主サイトが各サイトに、コミットできるかを問い合わせます。各サイトは、あとでコミットもロールバックもできるように、更新の内容をログに記録します。記録できたサイトは「準備OK」と返し、この時点ではまだ確定しません。ログを使って更新をやり直したり取り消したりする仕組みは、障害回復の記事で説明しています。
第2相では、全サイトのOKがそろったときだけ、主サイトがコミットを指示します。1つでも準備できないサイトがあれば、主サイトは全サイトにロールバックを指示します。全サイトがそろってコミットするか、そろって取り消すかのどちらかになります。
次の図では、振替の例で3つの場面を1段ずつ進めて比べられます。2相で全サイトが準備できた場合、2相でサイト2が返事をしない場合、問い合わせをせずにコミットしてサイト2が故障した場合です。
主サイトが、
主サイトが、
口座Aは
全サイトの
主サイトが、
主サイトが、
振替は
主サイトは、
主サイトが、
この
口座Aから
サイト2は、
2相コミットメントでは、サイト2が返事をしなくても、全体が取り消されて口座の金額は食い違いません。問い合わせをしないやり方では、サイト1だけが確定して、1万円が消えた状態になります。問い合わせの段階を1つ足したことで、片方のサイトだけが確定する事態を防いでいます。
準備OKのあとに主サイトが止まると、各サイトは待たされる
2相コミットメントにも弱点があります。「準備OK」と返したサイトは、主サイトの決定を待ちます。コミットするかロールバックするかを、自分では決めません。
この状態で主サイトが故障したり、通信が切れたりすると、各サイトは決定を受け取れません。決定が届くまで、そのトランザクションの結果は未定のままです。その間もロックは持ったままなので、同じデータを更新しようとするほかのトランザクションは待たされます。
障害が直ると、各サイトは主サイトの決定を確かめて、コミットかロールバックのどちらかで終わらせます。Oracle Databaseでは、この解決を専用のプロセスが自動で行います。準備した状態はディスクに記録されているので、待っている側のサイトが再起動しても、準備OKの状態は消えません。
PostgreSQLでは、第1相にあたる命令がPREPARE TRANSACTIONです。第2相にあたる命令は、確定するCOMMIT PREPAREDと、取り消すROLLBACK PREPAREDです。公式の説明では、これらはアプリケーションが直接使うものではありません。複数のデータベースをまとめて管理する、外部のトランザクション管理ソフトが使う命令です。準備したトランザクションは、COMMIT PREPAREDかROLLBACK PREPAREDが実行されるまで、ロックを持ったまま残ります。
参考にした資料
- Oracle Database 19c Administrator's Guide「Distributed Database Concepts」(分散データベースの定義、サイトの自律性、透過性)
- Oracle Database 19c Administrator's Guide「Distributed Transactions Concepts」(2相コミットの準備と確定、決定を待つ状態の解決)
- PostgreSQL Documentation「PREPARE TRANSACTION」(2相コミットの準備の命令)
- PostgreSQL Documentation「High Availability, Load Balancing, and Replication」(同期と非同期の違い)
練習問題(全5問)
正解:データが
透過性とは、
正解:レプリケーション
レプリケーションは、
正解:コミットできる
第1相では、
正解:全サイトに
2相コミットメントでは、
正解:主サイトの
準備OKと
選んでから「採点する」を押すと、解説つきで答え合わせができます。
関連記事
おすすめの本 PR
セキュリティとデータベースは、基本情報技術者試験の対策本でまとめて学べます。

