MVCC理论

作者: 刘一一同学 | 来源:发表于2019-09-15 09:11 被阅读0次

    1. 什么是MVCC

    MVCC(Muti-Version Concurrency Control)是多版本并发控制的方法,一般在数据库关系系统中,实现对数据库并发访问。在MySQL中,MyISAM使用的是表级锁,而InnoDB使用的是行级锁,其中默认的隔离级别Repeat Read(可重复读)采用的是乐观锁,而乐观锁的实现采用的就是MVCC,其较低系统开销,才早就了InnoDB强大的事务处理能力。

    MVCC主要解决读写互相不阻塞问题,每次更新都会产生一个新的版本,读的话可以读历史版本(某个时间点的快照),但MVCC不能解决幻读。

    2. MVCC具体实现

    InnoDB的MVCC是通过在每行记录后面保存两个隐藏的列来实现的,分别保存这条行的创建时间和行的删除时间。这里的时间并不是实际的时间值,而是系统版本号(事务的ID)。事务开始时刻的系统版本号会作为事务的ID,每次执行一个新事务,系统版本号就会自动递增。

    // 假设版本号从1开始
    create table yang( 
    id int primary key auto_increment, 
    name varchar(20));
    

    2.1 插入操作(INSERT)

    // 第一个事务ID为1
    start transaction;
    insert into yang values(NULL,'yang') ;
    insert into yang values(NULL,'long');
    insert into yang values(NULL,'fei');
    commit;
    

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

    id name 创建时间(事务ID) 删除时间(事务ID)
    1 yang 1 undefined
    2 long 1 undefined
    3 fei 1 undefined

    2.2 查询操作(SELECT)

    InnoDB会根据以下两个条件检查每行记录:

    • 行的创建版本号小于<=事务的版本号。
    • 行的删除版本号>事务的版本号。

    2.3 删除操作(DELETE)

    // 第二个事务ID为2
    start transaction;
    select * from yang;  // (1)
    select * from yang;  // (2)
    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 undefined

    然后接着执行事务2中的(2),由于id=4的创建时间(事务ID)为3,执行当前事务的ID为2,而InnoDB只会查找事务ID<=当前事务ID的数据行,所以事务3中的(2)不能获取id=4的数据行,在事务3中的两条Select语句检索的数据如下表所示:

    id name 创建时间(事务ID) 删除时间(事务ID)
    1 yang 1 undefined
    2 long 1 undefined
    3 fei 1 undefined
    • 假设2:在执行这个事务ID为2的过程中,刚执行到(1),假设事务执行完事务3后,接着又执行了事务4。
    // 第四个事务ID为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),由于创建时间(事务ID)< 当前事务ID ,删除时间 > 当前事务ID,因此事务ID为2的事务(2)的检索的数据如下表所示:

    id name 创建时间(事务ID) 删除时间(事务ID)
    1 yang 1 4
    2 long 1 undefined
    3 fei 1 undefined

    2.4 更新操作(UPDATE)

    InnoDB执行Update,实际上是新插入了一行记录,并保存其创建时间为当前事务的ID,同时保存当前事务ID到要Update的行的删除时间。

    • 假设3:在执行完事务2的(1)后又执行,其它用户执行了事务3、4。这时,又有一个用户对这张表执行了Update操作。
    // 第5个事务ID为5
    start transaction;
    update yang set name='Long' where id=2;
    commit;
    

    根据Update的更新原则,首先插入一条数据,并将原数据行的删除时间(事务ID)更新为本次事务ID,如下表所示:

    id name 创建时间(事务ID) 删除时间(事务ID)
    1 yang 1 4
    2 long 1 5
    3 fei 1 undefined
    4 tian 3 undefined
    4 tian 3 undefined

    继续执行事务2的(2),检索的数据如下表所示:

    id name 创建时间(事务ID) 删除时间(事务ID)
    1 yang 1 4
    2 long 1 5
    3 fei 1 undefined

    结果和事务2中(1)相同。

    相关文章

      网友评论

        本文标题:MVCC理论

        本文链接:https://www.haomeiwen.com/subject/orlbyctx.html