MVCC、正式名は Multi-Version Concurrency Control で、複数バージョンの同時実行制御です。 MVCC はマルチ同時実行制御方式であり、データベースへの同時アクセスを実現し、プログラミング言語でトランザクション メモリを実装するためにデータベース管理システムで一般に使用されます。
MySql が 5.5 以降、MyISAM ストレージ エンジンから InnoDB ストレージ エンジンに変更されたことはわかっています。主な理由は、InnoDB がトランザクションをサポートしているため、複数のスレッドが同時に実行されると同時実行性の問題が発生する可能性があるためです。このとき、同時実行性を制御できる方式が登場する可能性があり、MVCCがその役割を果たします。
MVCC は主に、アンドゥ ログ バージョン チェーンと ReadView によって実装されます。
Undo ログは主に、トランザクションがロールバックされたときに元のデータを復元するために使用されます。
mysql が SQL を実行すると、論理的に逆の 1 日分のログが UNDO ログに保存されます。したがって、アンドゥログに記録される内容も論理的なログとなります。
しかし、mysql が Insert ステートメントを実行すると、今回挿入された主キー ID が undo ログに記録されます。トランザクションがロールバックされると、delete はこの ID を削除します。
update ステートメントを実行すると、MySQL は変更前のデータを UNDO ログに保存します。トランザクションがロールバックされると、元のデータを取得するために再度更新が実行されます。
MySQL が delete ステートメントを実行すると、削除前のデータが undo ログに保存されます。トランザクションがロールバックした場合は、再度insertを実行し、元のデータを挿入してください。
データベースの 4 つの主要な特徴 - アトミック性、つまりトランザクションは分割不可能で、すべて成功するかすべて失敗するかのいずれかであり、最下層は UNDO ログによって実現されます。特定のステートメントの実行が失敗すると、前のトランザクションのステートメントがロールバックされます。
データベースの各行には、実際のデータを保存するだけでなく、3 つの非表示列もあります。 columns 列: row_id、trx_id、および roll_pointer
row_id、行番号:
現在のテーブルに整数の主キーがある場合type、次に row_id 値は主キーの値です
整数型の主キーがない場合、MySQL はフィールドの順序に従って整数型の空でない一意のインデックスを row_id として選択します
どちらも見つからない場合は、自動的に拡張されるものが作成されます。 row_id
trx_id として整数、トランザクション番号:
トランザクションの実行が開始されると、MySQL はトランザクションにグローバルにインクリメントされたトランザクション ID を割り当てます。
その後、トランザクションが追加、変更、削除などの操作を実行すると、自身のトランザクション ID が trx_id に記録されます。
roll_pointer、ロールバック ポインター:
トランザクションによって現在のデータが変更されると、古いデータが次の場所に記録されます。アンドゥ ログでは、データは現在の行に書き込まれ、現在の roll_pointer は直前のアンドゥ ログを指すため、roll_pointer を使用して行の前のバージョンを見つけることができます。
行を変更するトランザクションがある場合、UNDO ログが継続的に生成され、最終的に UNDO ログのバージョン チェーンが形成されます。
最初に、次のステートメントを使用して標準テーブルを作成します
CREATE TABLE `student` ( `id` INT ( 11 ) NOT NULL AUTO_INCREMENT, `name` VARCHAR ( 255 ) NOT NULL, `age` INT ( 11 ) NOT NULL, PRIMARY KEY ( `id` ) USING BTREE ) ENGINE = INNODB;
次に、最初のトランザクションであるトランザクションを開きます。 id が 1 の場合、次の insert ステートメントを実行します。
INSERT INTO student VALUES ( 1, "a", 24 );
現在の図は次のようになります。
データが新しく挿入されたため、roll_pointer が指す undo ログは空です。
次に、割り当てられたトランザクション ID が 2 の 2 番目のトランザクションを開き、次の変更コマンドを実行します。
UPDATE student SET NAME = 'b' WHERE id = 1;
現在の図は次のように変更されます:
3 番目のトランザクションが開かれ、割り当てられたトランザクション ID が 3 である場合、次の変更コマンドを実行します。
UPDATE student SET age = 25 WHERE id = 1;
図は次のようになります:
#各トランザクションが行を変更すると、以前のバージョンを保存するために元に戻すログが生成されます。生成されたばかりの UNDO ログへの roll_pointer のバージョン。
したがって、roll_pointer は、これらの異なるバージョンの UNDO ログを直列に接続して、UNDO ログのバージョン チェーンを形成できます。
まず、スナップショットの読み取りと現在の読み取りについて理解する必要があります
スナップショットの読み取り: 単純な選択クエリ、つまり、選択 … ロックは含まれません共有モードでは、更新のために … を選択すると、データの履歴バージョンを読み取ることができます。
現在の読み取り値: 次のステートメントはすべて現在の読み取り値であり、常に最新バージョンを読み取り、読み取られた最新バージョンをロックします。
select ... lock in share mode select ... for update insert update delete
トランザクションが各スナップショット読み取りを実行するとき、またはトランザクションが初めてスナップショット読み取りを実行するときに、一貫したビュー、つまり ReadView が生成されます。
ReadView の機能は、UNDO ログ バージョン チェーン内のどのデータが現在のトランザクションに表示されるかを判断することです。
m_ids
ReadView が作成された時点では、A mysql 内のすべてのコミットされていないトランザクション ID のコレクション。
min_trx_id
m_ids中的最小值
max_trx_id
mysql即将为下一个事务分配的事务id,并不是m_ids中的最大值。
creator_trx_id
即创建此ReadView的事务id
简要的示意图如下:
那么事务在执行快照读时,可以通过以下的规则来确定undo log版本链上的哪个版本数据可见。
如果当前undo log的版本的trx_id
如果当前undo log的版本的trx_id≥max_trx_id,说明该版本对应的事务在生成ReadView之后才开始的,因此是不可见的。
如果当前undo log的版本的trx_id∈[min_trx_id,max_trx_id),如果在这个范围里,还要判断trx_id是否在m_ids中:
在m_ids中,说明版本对应的事务未提交,因此是不可见的。 不在m_ids中,说明版本对应的事务已经提交,因此是可见的。
如果当前undo log的版本的trx_id=creator_trxt_id,说明事务正在访问自己修改的数据,因此是可见的。
当undo log版本链表的头结点数据被判定为不可见时,则利用roll_pointer找到上一个版本,再进行判断。如果整个链表中都没有找到可见的数据,则代表当前的查询找不到数据。
以上がMySQL の MVCC メカニズムとは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。