初心者に向けるTiDBの学習 ~ストレージ編 第3回~


初心者に向けるTiDBの学習メニュー

初心者に向けるTiDBの学習 ~ストレージ編 第1回~
初心者に向けるTiDBの学習 ~ストレージ編 第2回~
初心者に向けるTiDBの学習 ~ストレージ編 第3回~ <- 今ここ
初心者に向けるTiDBの学習 ~コンピューティング編 第1回~
初心者に向けるTiDBの学習 ~コンピューティング編 第2回~
初心者に向けるTiDBの学習 ~スケジューリング編~

初心者に向けるTiDBの学習のストレージ編 第1回ストレージ編 第2回でデータの格納、キーバリュー、RocksDB、Raftとリージョンなど概念を紹介いたしました。ストレージ編の最終回でMVCCとトランザクションを紹介します。みなさんは最後まで頑張りましょう。

MVCC

多くのデータベースでは、複数バージョンの同時制御(MVCC: Multi-Version Concurrency Control)が行われます。TiKVも例外ではありません。MVCCを介さずに2つのクライアントがキーの値を同時に更新すると、データはロックされます。分散シナリオでは、このような処理はパフォーマンス問題やデッドロック問題につながります。

TiKVは、キーにバージョンを付記することによってMVCCを実現します。MVCCを行わないと、TiKVのデータレイアウトは次のようになります。

    Key1 -> Value
    Key2 -> Value
    ……
    KeyN -> Value

MVCCを行うと、TiKV内のキー配列は次のようになります。

    Key1-Version3 -> Value
    Key1-Version2 -> Value
    Key1-Version1 -> Value
    ……
    Key2-Version4 -> Value
    Key2-Version3 -> Value
    Key2-Version2 -> Value
    Key2-Version1 -> Value
    ……
    KeyN-Version2 -> Value
    KeyN-Version1 -> Value
    ……

キーに複数のバージョンが存在する場合は、一番大きい数値を最初に配置します(必要に応じ、キーとは順序付けられた配列だと説明したキーバリューセクションにもう一度目を通してください)。このように、キーにバージョンを付記して値を取得するときには、キーとバージョンを使用したMVCCのキー(Key-Version)を構築できます。続いて、Seek(Key-Version)を直接実行し、このKey-Version以降である最初の位置を見つけることができます。詳細については、「MVCC in TiKV (TiKVにおけるMVCC)」を参照してください。

トランザクション

TiKVのトランザクションはパーコレーターモデルを採用しており、多数の最適化が行われています。ここで触れておきたいことは、TiKVのトランザクションは楽観的なロックを使用するということです。TiKVのトランザクションは、実行プロセスでは書き込み衝突を検出しません。衝突を検出するのはコミットフェーズ内だけです。先にコミットを終了するトランザクションは正常に書き込まれますが、他のトランザクションは再試行します。その会社の書き込み競合が深刻でなければ、このモデルのパフォーマンスはきわめて良好です。たとえば、大きなテーブル内の複数のデータ行をランダムに更新するといった作業に難なく対応できます。しかし、書き込み競合が深刻だと、パフォーマンスは低いものとなります。カウンタは極端な例と考えてください。多くのクライアントがわずかな行を同時に更新するという状況は、深刻な競合と多数の無効な再試行につながります。

後記

ストレージ編の記事では、TiKVの基本概念と若干の細部、この分散型トランザクションキーバリューエンジンのレイヤー構造、マルチデータセンターのディザスタリカバリを実現する方法などを紹介しました。次の記事では、分散データベースTiDBのコンピューティングについて紹介します。