博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MVCC实现机制
阅读量:5149 次
发布时间:2019-06-13

本文共 2099 字,大约阅读时间需要 6 分钟。

1. MVCC简介

1.1 什么是MVCC

  MVCC(Multiversion concurrency control )是一种多版本并发控制机制。

1.2 MVCC是为了解决什么问题?

  并发访问(读或写)数据库时,对正在事务内处理的数据做多版本的管理。以达到用来避免写操作的堵塞,从而引发读操作的并发问题。

  大家都应该知道,锁机制可以控制并发操作,但是其系统开销较大,而MVCC可以在大多数情况下代替行级锁,使用MVCC,能降低其系统开销。

1.3 MVCC实现

  MVCC是通过保存数据在某个时间点的快照来实现的。不同存储引擎的MVCC实现是不同的,典型的有乐观并发控制和悲观并发控制。当我们创建表完成后,mysql会自动为每个表添加 数据版本号(最后更新数据的事务id)db_trx_id 删除版本号 db_roll_pt (数据删除的事务id) 事务id由mysql数据库自动生成,且递增。

2.MVCC 具体实现分析

2.1 MVCC逻辑流程-插入(insert)

  如下图,同一事务中(假设事务id=1)插入两条记录,记录的数据版本号为事务id=1,删除版本号为null

start transaction;(事务id为1)INSERT INTO user (name,sex) VALUES ('张三','男');INSERT INTO user (name,sex) VALUES ('李四','男');commit;

  对应在数据中的表如下(后面两列是隐藏列,我们通过查询语句并看不到)

  

2.2 MVCC逻辑流程-查询(select)

  查询时需要同时满足以下两个条件

  1、查找数据版本号,早于(小于等于)当前事务id的数据行。 这样可以确保事务读取的数据是事务之前已经存在的。或者是当前事务插入或修改的。
  2、查找删除版本号为null 或者大于当前事务版本号的记录。 这样确保取出来的数据在当前事务开启之前没有被删除。

  如下图,假如有一个事务中执行查询(假设事务id=2)

start transaction;(事务id为2)select * from user where sex = '男';  --(1)select * from user where sex = '男';  --(2)commit;

  假设在执行这个事务ID为2的过程中,刚执行到(1),这时有另一个事务(假设事务id=3)往这个表里插入了一条数据; 

start transaction;(事务id为3)INSERT INTO user (name,sex) VALUES ('王五','男');commit;

  此时表中的数据如下:

  

  然后接着执行事务 id=2 中的(2),由于id=3的数据的创建时间(事务ID为3),执行当前事务的ID为2,而InnoDB只会查找事务ID小于等于当前事务ID的数据行,所以 id=3 的数据行并不会在执行事务 id=2 中的 (2) 被检索出来。在事务 id=2 中的两条select 语句检索出来的数据都只会下表:

  

2.3 MVCC逻辑流程-删除(delete)

  如下图,假如有一个事务中执行查询(假设事务id=4)

start transaction;(事务id为4)select * from user where sex = '男';  --(1)select * from user where sex = '男';  --(2)commit;

  假设事务 id=4 刚执行到(1),此时有另外一个事务 id=5 执行了删除语句,会更新数据的删除版本号为当前事务id = 5 

start transaction;(事务id为5)DELETE FROM user WHERE id = 1;commit;

  此时数据库表中数据如下:

  

  接着执行事务 id=4的事务(2),根据SELECT 检索条件可以知道,它会检索创建时间(创建事务的ID)小于当前事务ID的行和删除时间(删除事务的ID)大于当前事务的行,表中id=1的行由于删除时间(删除事务的ID)大于当前事务的ID,所以事务 id=2 的(2)在执行的时候也会把表中 id=1 的数据检索出来,所以事务4中的两条select 语句检索出来的数据都如下:

  

2.4 MVCC逻辑流程-修改(update)

  可以理解为,当一个事务中 修改一条记录时, 是先复制该数据,新数据数据版本号为当前事务id,删除版本号为 null 。然后更新 原来数据的删除版本号为 当前事务id。如下:

  假如一个事务 id=6 执行了一条update语句

start transaction;(事务id为6)UPDATE user SET name='李四1' WHERE id = 2commit;

  执行结果如下:

  

 

 

 

 

 

转载于:https://www.cnblogs.com/luchangyou/p/11321607.html

你可能感兴趣的文章
Ubuntu配置ssh及vnc
查看>>
字符串的查找删除
查看>>
NOI2018垫底记
查看>>
快速切题 poj 1002 487-3279 按规则处理 模拟 难度:0
查看>>
Codeforces Round #277 (Div. 2)
查看>>
【更新】智能手机批量添加联系人
查看>>
NYOJ-128前缀式计算
查看>>
淡定,啊。数据唯一性
查看>>
深入理解 JavaScript 事件循环(一)— event loop
查看>>
Hive(7)-基本查询语句
查看>>
注意java的对象引用
查看>>
C++ 面向对象 类成员函数this指针
查看>>
Python字符编码
查看>>
leetcode 49. 字母异位词分组(Group Anagrams)
查看>>
NSPredicate的使用,超级强大
查看>>
自动分割mp3等音频视频文件的脚本
查看>>
判断字符串是否为空的注意事项
查看>>
布兰诗歌
查看>>
python13 1.函数的嵌套定义 2.global、nonlocal关键字 3.闭包及闭包的运用场景 4.装饰器...
查看>>
例6-5
查看>>