MySQL関連(F) - 実装のトランザクション分離レベル(MVCC)

序文

前の記事で私たちは4つのプロパティACID、およびInnoDBトランザクション分離レベルのMySQLの事務を導入RUは、RCは、RRは、直列化は、私は、関連する子を販売し、時間の終わりに、私たちはInnoDBトランザクションについて考えてみましょうMySQLでの分離レベルを達成する方法である、あなたはあまりにもZeyangと思うかどうか知りませんが、とにかく、我々は、トランザクション分離レベルの実装今日の話を続けるためにここにいます。

チケットの最初の古いルール、:

  1. MySQL関連() - クエリがどのように実行されます
  2. MySQL関連(2) - 更新文は、それを実装する方法であります
  3. 関連のMySQL(サイドストーリー) - InnoDBの論理ストレージ構成
  4. 関連のMySQL(C) - B +ツリーの詳細のインデックスデータモデルと控除
  5. MySQL関連(4) - パフォーマンス最適化のキーインデックス
  6. MySQL関連(E) - 特性とトランザクション分離レベルの詳細

マインドマップ先に述べたように、我々は完全な高精細写真返信MySQLのマインドマップにしたいと、下の私の公共のマイクロチャネル番号を取得するために行くことができる[6] Xixuanは次のとおりです。
ここに画像を挿入説明

テキスト

散歩のボディ

私たちは、最初にあなたの時間の一貫性の問題を解決したい場合は、私がやるべきか、一貫性のある結果がデータ二回取引、達成するために、トランザクションの分離を読ん確保するために、およそと思いますか?私たちはいくつかの方法は何ですか?それのあなたの考えは何ですか?

全体的に、我々は持っている2種類のプログラムを。

LBCC

まず、私たちは私が二度同じデータを読む前に、私が操作するためのデータがロックしたときに、私はデータを読み取ることを保証するために持っているように、他のトランザクションが行に変更することはできません。このプログラムは、我々はコントロールのロックベースの同時実行制御(LBCC)ロックベースの並行処理を呼び出します。

ロックベースのトランザクション分離を達成する場合にのみ、トランザクションは、他の時間を変更することはできません読み取ると、その手段は、同時読み取りと書き込み操作をサポートしていない、と私たちのアプリケーションのほとんどは、あまりこの意志を読み書きしています大幅に運用データの効率に影響を与えます。

MVCC

所以我们还有另一种解决方案,如果要让一个事务前后两次读取的数据保持一致,那么我们可以在修改数据的时候给它建立一个备份或者叫快照,后面再来读取这个快照就行了。这种方案我们叫做多版本的并发控制 Multi Version Concurrency Control (MVCC)。

MVCC 的核心思想是: 我可以查到在我这个事务开始之前已经存在的数据,即使它在后面被修改或者删除了。在我这个事务之后新增的数据,我是查不到的。

  • 问题:这个快照什么时候创建?读取数据的时候,怎么保证能读取到这个快照而不是最新的数据?这个怎么实现呢?

InnoDB 为每行记录都实现了两个隐藏字段:

DB_TRX_ID,6 字节:插入或更新行的最后一个事务的事务 ID,事务编号是自动递增的(我们把它理解为创建版本号,在数据新增或者修改为新数据的时候,记录当前事务 ID)。

DB_ROLL_PTR,7 字节:回滚指针(我们把它理解为删除版本号,数据被删除或记录为旧数据的时候,记录当前事务 ID)。

我们把这两个事务 ID 理解为版本号。
ここに画像を挿入説明

第一个事务,初始化数据(检查初始数据)

//Transaction 1

begin;

insert into mvcctest values(NULL,'Jerry') ;

insert into mvcctest values(NULL,'jack') ;

commit;

此时的数据,创建版本是当前事务 ID,删除版本为空:

id name 创建版本 删除版本
1 Jerry 1 undefined
2 jack 1 undefined

第二个事务,执行第 1 次查询,读取到两条原始数据,这个时候事务 ID 是 2:

// Transaction 2
begin;
select * from mvcctest ;	-- (1) 第一次查询

第三个事务,插入数据:

// Transaction 3
begin;
insert into mvcctest values(NULL,'tom') ;
commit;

此时的数据,多了一条 tom,它的创建版本号是当前事务编号,3:

id name 创建版本 删除版本
1 Jerry 1 undefined
2 jack 1 undefined
3 tom 3 undefined

第二个事务,执行第 2 次查询:

Transaction 2
select * from mvcctest ;	(2) 第二次查询

MVCC 的查找规则:只能查找创建时间小于等于当前事务 ID 的数据,和删除时间大于当前事务 ID 的行(或未删除)。

也就是不能查到在我的事务开始之后插入的数据,tom 的创建 ID 大于 2,所以还是只能查到两条数据。

第四个事务,删除数据,删除了 id=2 jack 这条记录:

Transaction 4
begin;
delete from mvcctest where id=2;
commit;

此时的数据,jack 的删除版本被记录为当前事务 ID,4,其他数据不变:

id name 创建版本 删除版本
1 Jerry 1 undefined
2 jack 1 4
3 tom 3 undefined

在第二个事务中,执行第 3 次查询:

Transaction 2
select * from mvcctest ;	(3) 第三次查询

查找规则:只能查找创建时间小于等于当前事务 ID 的数据,和删除时间大于当前事务 ID 的行(或未删除)。

也就是,在我事务开始之后删除的数据,所以 jack 依然可以查出来。所以还是这两条数据。

第五个事务,执行更新操作,这个事务事务 ID 是 5:

Transaction 4
begin;
update mvcctest set name ='Mic' where id=1;
commit;

此时的数据,更新数据的时候,旧数据的删除版本被记录为当前事务 ID 5(undo),产生了一条新数据,创建 ID 为当前事务 ID 5:

id name 创建版本 删除版本
1 Jerry 1 5
2 jack 1 4
3 tom 3 undefined
1 Mic 5 undefined

第二个事务,执行第 4 次查询:

// Transaction 2
select * from mvcctest ;	(4) 第四次查询

查找规则:只能查找创建时间小于等于当前事务 ID 的数据,和删除时间大于当前事务 ID 的行(或未删除)。

因为更新后的数据 Mic 创建版本大于 2,代表是在事务之后增加的,查不出来。

而旧数据 Jerry 的删除版本大于 2,代表是在事务之后删除的,可以查出来。

通过以上演示我们能看到,通过版本号的控制,无论其他事务是插入、修改、删除,第一个事务查询到的数据都没有变化。

在 InnoDB 中,MVCC 是通过 Undo log 实现的。

Oracle、Postgres 等等其他数据库都有 MVCC 的实现。

需要注意,在 InnoDB 中,MVCC 和锁是协同使用的,这两种方案并不是互斥的。第一大类解决方案是锁,锁又是怎么实现读一致性的呢?

关于锁的知识已经在快马加鞭准备了,且听下回分解~

By the way

有问题?可以给我留言或私聊
有收获?那就顺手点个赞呗~

当然,也可以到我的公众号下「6曦轩」,

回复“学习”,即可领取一份
【Java工程师进阶架构师的视频教程】~

回复“面试”,可以获得:
【本人呕心沥血整理的 Java 面试题】

回复“MySQL脑图”,可以获得
【MySQL 知识点梳理高清脑图】

私の毛布、訓練を受けたプログラマ、PHPの、Androidとハードウェアが行っているが、最終的にJavaの実行に注力することにしたので、そう何の問題は、公開討論の質問の数であってもよい(感情的な話技術ハッハッハすることができます)を参照してください言葉は歓迎の注意~~~、Javaコア分析知識、経歴、インタビューの要約及びその他の物品は時折プッシュ出力に準拠し、サーバアーキテクチャ上、進行あなたと一緒に学ぶことを期待して、できるだけ早く返信されます

ここに画像を挿入説明

公開された34元の記事 ウォンの賞賛9 ビュー10000 +

おすすめ

転載: blog.csdn.net/weixin_42669785/article/details/104209243