何MVCCこと?

MVCCは、マルチバージョン同時実行制御の略で、通常のシーンで使用されるデータベースなど、複数バージョンの同時実行制御


マルチバージョン並行性制御(MCCまたはMVCC)は、一般にトランザクショナルメモリを実装するためにデータベースへとプログラミング言語の同時アクセスを提供するために、データベース管理システムによって使用される並行性制御方法です。


もし何の同時実行制御しないユーザーが同時にデータを読み書きので、もし、それが一貫性のないデータ読み出し状況かもしれません。薄い空気が消えたからお金を感じるだろう、例えば、口座のBへの銀行振込みのAお金が引き落とされたときに、そしてお金は自分の残高を表示し、その後、Bのアカウントにユーザーを追加されていません。MySQLの分離は、このような問題を解決するために使用されますが、アイソレーションが異なる同時実行制御によって達成されます。口座間振替、口座をチェックし、このアプローチは、問題を解決することができますが、許可され、確かに単純すぎると、粗、低効率されていない場合、前の質問のために、簡単な同時実行制御は、オペレーションのシリアライズを読み書き話すことです。同時実行制御のシリアライズと比較すると、MVCCは、このアプローチに、より少ない現代のインターネットシーンを読み書きするために、かなり高いパフォーマンスを影響を読み書きするという利点があります。


MVCCを使用すると、データ・ストレージ・システムを更新する必要がある場合MVCCはすぐに新しいデータで元のデータを上書きしませんが、このレコードの新しいバージョンを作成するために実装し、データ制御の同時保存複数のバージョンによって達成されます。ほとんどのデータベースシステムでは、ストレージはデータパートと元に戻すログに分割されます、データ部は、トランザクション・データを格納するために使用され提出されており、アンドゥログは、データの古いバージョンを格納するために使用されます。操作は、競合、パフォーマンスを大幅に向上させることはありません読み取りと書き込みができます分離の複数のバージョンがあり、操作は、バージョンの前に、データを読み取るために必要な読み込み、書き込み。

アップデートにロールバックを記録しながら、各レコードにはなるだろう。同じレコードの複数のバージョンは、マルチバージョン同時実行制御データベースであるシステムで存在することができます。(MVCC)。


MVCC効果

時間は、時間= 1でMVCCバージョンデータ、時間に応じて決定された場合は、データベースの状態は、次のように


時間 レコードのA レコードのB

「レコードA場合は、時間= 0」 「レコードB時点= 0」

「レコードA場合は、時間= 1」  

時間= 0でのトランザクション時間は、データが読み出され、オンになっている場合、システムは、実際の時間0と各レコードの1から3つのレコード、レコードAに格納され、この時間は、レコードは、レコードBです。


レコードのA レコードのB

「レコードA場合は、時間= 0」 「レコードB時点= 0」

時の開口部が=、その後、データが読み込まれ、このトランザクションの場合:


レコードのA レコードのB

「レコードA場合は、時間= 1」 「レコードB時点= 0」

ケースは読み取りが懸念されるため、トランザクションが唯一、このリリースより前にあるバージョンとのデータの最新の作品を読むことができ、上で見たことができる場合、取引トランザクションXがレコードBを録音C挿入、および更新するには時間= 2、で、

次のようにしかし、トランザクションはデータベースの状態、その後、コミットされていません。


時間 レコードのA レコードのB 録音C

「レコードA場合は、時間= 0」 「レコードB時点= 0」  

「レコードA場合は、時間= 1」  

2(コミットされていません) 「レコードB時点= 2」 「レコードCとき時間= 2」

この時間は、他のトランザクションがでているものを読むのだろうか?この場合は、他の企業がシステムの最新バージョンを見ることができます読んシステムは= 1時間であるということです、それはまだトランザクションX上書きされたデータを読んでいないだろうとき、データはまだこの時点で読み込まれます。


レコードのA レコードのB

「レコードA場合は、時間= 1」 「レコードB時点= 0」

メカニズムのこのバージョンに基づいて、別のトランザクションによってそこに読まれないであろう他のオフィス・システムはまだ= 1時間の状態に見られるようにレコードレコードを読ん中間結果BとCは、トランザクションXに更新されていない間に発生しました。


言ったように、各トランザクションは、私はMySQLのMVCC実装を紹介しますの下に具体的にどのようなデータのバージョン、これはMVCCによって決定されるが、異なるシステムを実装して表示されるはずです。読み出したデータに加えて、以下の現在のシステムの等しい外部バージョンが書き込み総務に提出されているでなければなりません

これは、提出の現在のバージョンよりも大きいこと、そしてここに書き込みまたは更新トランザクションの数を開く、= 2時間の時間と、問題があるかどう考えて、彼らは同じ時間を提出しようとすると、データベースが発見されたトランザクションが存在しなければならない必要があります状態の時間= 2、

だから、どのようにこの取引を行うには?あなたは考えることができます。


MySQL的MVCC

MySQL的Innodb引擎支持多种事务隔离级别,而其中的RR级别(Repeatable-Read)就是依靠MVCC来实现的,MySQL中MVCC的版本指的是事务ID(Transaction ID),首先来看一下MySQL Innodb中行记录

的存储格式,除了最基本的行信息外,还会有一些额外的字段,这里主要介绍和MVCC有关的字段:DATA_TRX_ID和DATA_ROLL_PTR,如下是一张表的初始信息:


Primary Key Time Name DATA_TRX_ID DATA_ROLL_PTR

2018-4-28 Huan NULL

这里面为了便于说明,表中DATA_TRX_ID和DATA_ROLL_PTR存的值是Mock的值:


DATA_TRX_ID:最近更新这条记录的Transaction ID,数据库每开启一个事务,事务ID都会增加,每个事务拿到的ID都不一样

DATA_ROLL_PTR:用来存储指向Undo Log中旧版本数据指针,支持了事务的回滚

最开始的记录无法回滚,所以DATA_ROLL_PTR为空。


这个时候开启事务A(事务ID:2),对记录进行了更新,但还没有提交,那么当前的数据为:


Transaction 1


可以看到,旧的数据会被存到Undo Log中,通过当前记录中的DATA_ROLL_PTR关联,那么如果另一个事务中想读取该数据,读到的会是什么数据了?假如说另一个事务B在事务A之后开启(事务ID:3),

既然我们最开始说Innodb的MVCC是基于事务ID做的,那么既然事务B的事务ID比事务A的大,那么事务B就可以独到A还未提交的数据了,这明显和Innodb RR的定义不符合。实际上,事务读取时,

判断应该读取哪个版本的记录,有一个较为复杂的逻辑,不是单纯的和记录上的事务ID进行比较,假设当前读的事务ID为read_id,记录当前存储的事务ID为tid,当前系统中未提交的事务中                  郑州×××医院×××:http://myyk.familydoctor.com.cn/yiyuanzaixian/zztjyy//

(Read_View中)的最大最小事务ID分别为max_tid和min_tid,那么数据可见性判断流程为:


通过上图(这个图是通过分析网上的一些博客内容得到的,和实际MySQL的逻辑细节可能不一致),在来分析上文提到的Case,由于事务B的事务ID不满足read_id=tid||tid<min_tid的条件,

且该记录当前有DATA_ROLL_PTR,所以最后该事务B实际读取的是Undo Log中的记录:


Primary Key Time Name DATA_TRX_ID DATA_ROLL_PTR

2018-4-28 Huan NULL

需要注意的是,MySQL的MVCC和理论上的MVCC实际有所差异,MySQL同一时刻只允许一个事务去操作某条数据,该条数据上的操作实际是串行的,也就是说一条记录的有用版本实际就只会有当前记录

和一条Undo Log记录,是悲观锁的操作方式,而MVCC的定义上实际是乐观锁的操作方式,某一时刻记录可以存在很多个版本。