MySQL-InnoDB的MVCC

 
  InnoDB MVCC
  InnoDB 的 MVCC, 其实是通过 undo log 来实现的, 可以理解为是通过在每行记录后面保存两个隐藏的列来实现的, 分别保存了这个行的创建时间, 一个保存的是行的删除时间. 这里存储的并不是实际的时间值, 而是系统版本号(可以理解为事物的 Id), 每开始一个新的事物, 系统版本号就会自动递增, 事物开始时刻的版本号会作为事物 Id.
  对应在数据中的表如下(后面两列是隐藏列, 我们通过查询语句并看不到)

 

 
  SELECT
  InnoDB 会根据以下两个条件检查每行记录:
    1. InnoDB 只会查找版本早于当前事务版本的数据行(也就是 行 的系统版本号小于或等于事物的系统版本号), 这样可以确保事物读取的行, 要么是在事物开始前已经存在的, 要么是事物自身插入或者修改过的.
    2. 行 的删除版本要么未定义, 要么大于当前事务版本号( 这可以确保事物读取到的行, 在事物开始之前未被删除)
只有条件 1, 2 同时满足的记录, 才能返回作为查询结果
 
  DELETE
  InnoDB 会为删除的每一行保存当前系统的版本号( 事物ID) 作为删除标识
 
 
  看下面的具体例子分析: 第二个事物, Id为 2:
   
start transaction; 
select * from yang; 
select * from yang; 
commit;

  

 
  假设1:
    假设在执行这个事物 Id 为2的过程中, 刚执行到 (1), 这时, 有另一个事物 Id 为 3 往这个表里插入了一条数据; 这个事物 Id 为 3
    
start transaction;
insert into yang values(NULL,'tian');
commit;

  

 
   这时表中的数据如下:
id
name
创建时间(事务ID)
删除时间(事务ID)
1
yang
1
undefined
2
long
1
undefined
3
fei
1
undefined
4
tian
3
 
 
 
    然后接着执行事物 2 中的 (2), 由于 id = 4 的数据的创建时间(事物 Id = 3), 执行当前事物的 Id 为 2, 而 InnoDB 只会查找事物 Id 小于等于当前事务 Id的数据行, 所以 id = 4 的数据行并不会在执行事务 2 中的 (2) 被检索出来, 在事物 2 中的两条 select 语句检索出来的数据如下
id
name
创建时间(事务ID)
删除时间(事务ID)
1
yang
1
undefined
2
long
1
undefined
3
fei
1
undefined
 
 
 
   假设2
    假设在执行这个事物 ID 为 2 的过程中, 刚执行到 (1), 假设事物执行完事物 3 后, 接着有执行了事物 4;
    
start transaction; 
delete from yang where id=1; 
commit;

  

 
   此时数据库中的表如下
id
name
创建时间(事务ID)
删除时间(事务ID)
1
yang
1
4
2
long
1
undefined
3
fei
1
undefined
4
tian
3
undefined
 
    接着执行事务 ID 为 2 的事物 (2), 根据 SELECT 检索条件可以知道, 它会检索创建时间( 创建事物的ID) 小于当前事物 ID 的行和删除事物的 ID 大于当前事务的行, 而 Id = 4 的行上面已经说过了, 而 Id = 1 的行由于删除时间 ( 删除事物 Id) 大于当前事务的 ID, 所以事物 2 的 (2) select * from yang 也会把 id = 1 的数据检索出来, 所以, 事物 2 中的两条 select 语句检索出来的数据都如下:
id
name
创建时间(事务ID)
删除时间(事务ID)
1
yang
1
4
2
long
1
undefined
3
fei
1
undefined
 
 
  UPDATE
    InnoDB 执行 UPDATE, 实际上是新插入了一行记录, 并保存其创建时间为当前事物的 ID, 同时保存当前事务 ID 到要 UPDATE 的行的删除时间.
  假设3:
    假设在执行完事物 2 的 (1) 后又执行, 其他用户执行了事物 3, 4, 这时, 又有一个用户对这张表执行了 UPDATE 操作:
  第 5 个事物:
    
start transaction; 
update yang set name='Long' where id=2;
commit;

  

    根据 UPDATE 的更新原则: 会生成新的一行, 并在原来要修改的列的删除时间上添加本事物 ID, 得到表如下:
id
name
创建时间(事务ID)
删除时间(事务ID)
1
yang
1
4
2
long
1
5
3
fei
1
undefined
4
tian
3
undefined
2
Long
5
undefined
 
  继续执行事物 2 的(2), 根据 select 语句的检查条件, 得到下表:
id
name
创建时间(事务ID)
删除时间(事务ID)
1
yang
1
4
2
long
1
5
3
fei
1
undefined
  还是和事物 2 中 (1) select 得到相同的结果.
 
 
 
 
 
 
posted @ 2022-11-10 17:52  茄子777  阅读(33)  评论(0编辑  收藏  举报