ツナワタリマイライフ

日常ネタから技術ネタ、音楽ネタまで何でも書きます。

Galera Clusterの同期の仕組みを公式ドキュメントから読み解く(4) ISOLATION LEVELS

はじめに

第4弾です。引き続き以下のページを訳していきます。

Technical Description — Galera Cluster Documentation

take-she12.hatenablog.com

take-she12.hatenablog.com

take-she12.hatenablog.com

とはいえ、、、今回の題である分離レベル(Isolation Level)はこちらの記事で触れました。が、復習の気持ちでやろう!

take-she12.hatenablog.com

ISOLATION LEVELS(分離レベル)

データベースシステムでは、トランザクションが同時発生する家庭でお互いに"分離"します。分離レベルによってトランザクションがお互いにどのように影響するのかが決まります。

INTRA-NODE VS. INTER-NODE ISOLATION IN GALERA CLUSTER

Galera Clusterでのクライアントセッションのために定められる分離レベルの話をする前に、シングルノードとクラスタトランザクションの間の分離を区別することは重要です。個々のクラスタノードはMySQLまたはInnoDBによってサポートされている分離レベルを拡張することができる。しかし、クラスタ内のノード間での分離レベルはレプリケーションプロトコルに影響される。それは別のノードで行われるトランザクションがが同一ノードで行われるトランザクションと独立に分離することができないからだろう。

クラスタ全体でサポートされる分離レベルは、以下3つ。

  • READ-UNCOMMITTED
  • READ-COMMITTED
  • REPEATABLE-READ

(訳注:SERIALIZABLEは出てこないんですね)

異なるノードでトランザクションが行われるので、分離は"最初にコミットしたものが勝者"というルールによって強化される。これはすなわちノード固有の"例外的な更新を破棄する"ことを除外する。(MySQL/InnoDBはこの振る舞いをする) これは異なる出力がトランザクションに依存するが、(同じノードで出されたトランザクションが成功し、同じトランザクションが別のノードで失敗すること)、同様のケースでスタンドアロンMySQL/InnoDBでは分離レベルが強くなる。

(訳注:何が言いたいかイマイチよくわからない。。。クラスタ内でトランザクションが強豪した場合、あるノードのトランザクションが勝ち、あるノードのトランザクションが負けることはそりゃそうかなって思う)

SERIALIZABLEの分離レベルは同じノードで行われたトランザクションの間でのみ有効であるため、結果的に(Galera Clusterでは)回避する必要がある。

ノード間でのデータ一貫性は常にクライアントによって選ばれる分離レベルに関係なく保証されます。しかし、食らう案とのロジックはコンフィグレーションでサポートされていない分離レベルに依存している場合破綻します。

UNDERSTANDING ISOLATION LEVELS

注意:警告:master-slaveモードでgalera clusterを使うとき、MySQLがサポートする4レベルを使うことができます。しかし、multi-masterモードの場合、REPEATABLE-READレベルのみ使うことができます。

READ-UNCOMMITTED

このトランザクションはコミットされていない別のトランザクションによってデータが変更され得るものです。

言い換えると、トランザクションは、コミットをせずに変更をロールバックした別のトランザクションによって結果的に存在しないデータを読み取ることもあるでしょう。これは"ダーティリード"として知られています。(訳注:一時的にコミット前のInnoDBのログあるいはバッファプールにのったデータのことをダーティリードと呼びます。これはまだ実際のデータファイルに書き込みされておらず、本来読み込まれるべきではないものです。) 事実上、READ-UNCOMMITTEDはまったく分離されていません。

READ-COMMITTED

このレベルではダーティリードができません。コミットされていない変更はトランザクションがコミットされるまで別のトランザクションにとって見えません。

しかし、この分離レベルではSELECTのqueryはコミットされたデータのスナップショットを用いるので、SELECTのqueryが実行される前にデータがコミットされます。結果的に、SELECTのqueryは、同じトランザクションが同時に実行されるとき、異なる結果を返すことになります。これはnon-repeatable readと呼ばれます。

(訳注:コミットされていない結果を読み取ることがないので、ダーティリードは発生しないが、別のトランザクションによってUPDATEなどの変更が行われた場合は同一トランザクション内で別の結果が返ってくることがありえるので、ファントムリードやNon-Repeatable Readが起こる)

REPEATABLE-READ

このレベルではnon-repeatable readsは起きません。SELECT queryがトランザクションの間で最初に行われたときにスナップショットが取られます。

スナップショットはSELECT queryのトランザクション全体を通じて維持されます。それは常に同じ返答が得られることとなります。このレベルは別のトランザクションによってデータが変更されたことを知ることができません。コミットされている、いないにかかわらず。これにより読み取りは繰り返し可能なままです。

(訳注:読み取りに関してはトランザクション実施時にSnapshotを取得するので、一貫して同じ値が得られる。しかし別のトランザクションによってINSERTが実施された場合はファントムリードが発生する。)

SERIALIZABLE

このレベルはトランザクションでアクセスするすべてのレコードをロックします。リソースはトランザクションが行われているテーブルにレコードを追加できないようにロックします。

SERIALIZABLEはファントムリードで知られているものを回避できる。ファントムリードが起きたとき、トランザクションでは2つの独立したqueryが実行され、2つめのquetが1つめものと比べて別の答えを返すときに発生する。

おわりに

今回は分離レベルを扱いました。まず分離レベルの違いによって起きる3つの不都合「ダーティリード」「ノンリピータブルリード」「ファントムリード」を抑えた上で、4つのレベルで何が起きるか起きないかを整理することが重要です。

個人的にはREAD-COMMITTEDとREPEATABLE-READの違いが結構分かりづらかったのですが、前者は別のトランザクションのUPDATEによって別の値がSELECTで読み取られてしまう(Non-Repeatable Read)に対して、後者はINSERTによって最初存在しなかったレコードが見えてくるファントムリードが起きる、という風に理解しました。

が、特にGalera Clusterに特化した話ではなく、RDBMS一般の議論なのかなと思いました。Galera Clusterは、特にマルチマスタの場合REPATABLE-READとなるようですね。