zoukankan      html  css  js  c++  java
  • 数据库事务隔离级别与MVCC

    数据库事务隔离级别

    事务隔离级别包括:读未提交(read uncommitted)读提交(read committed)可重复读(repeatable read)串行化(serializable)

    • 读未提交:一个事务还未提交时,它做的变更就被别的事务看到
    • 读提交:一个事务提交之后,它做的变更才会被其它事务看到
    • 可重复读:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的
    • 串行化:对于一行记录,读和写均会加锁。出现读写锁冲突时,后面的事务需要等待前一个事务执行完成。

    在实现上,数据库里面会创建一个视图,访问的时候以视图的逻辑结果为准。在可重复读隔离级别下,这个视图是在事务启动时创建的,整个事务存在期间都用这个视图。在读提交隔离级别下,这个视图是在每个SQL语句开始执行的时候创建的。这里需要注意的是读未提交隔离级别下直接返回记录上的最新值,没有视图概念;而串行化隔离级别下直接用加锁的方式来避免并行访问。

    数据库事务隔离级别和MVCC(多版本并发控制)的关系

    以下内容均是基于Mysql中Innodb引擎

    视图的概念

    1. 视图(View),是数据库中的虚拟表。数据库中只存放视图的定义,数据仍然保存在原来的基本表中。
    2. 一致性读视图(Consistent read view),Innodb引擎实现MVCC时使用,用于支持读提交和可重复读隔离级别的实现。

    MVCC

    Multi-Version Concurrency Control 多版本并发,MVCC 是一种并发控制的方法,用于实现对数据库的并发访问。InnoDB MVCC的实现基于Undo log,通过回滚段来构建需要的版本记录,通过Read view来判断哪些版本的数据可见。

    版本链

    对于InnoDB引擎的表来说,它的聚簇索引记录中的数据会包含两个必要的隐藏列trx_idroll_pointer

    trx_id: 每次一个事务对某条记录进行改动时,会把该事务的事务id赋值给trx_id

    roll_pointer: 每次对记录进行改动时,会把旧的版本写入undo log日志中,每条undo log也有一个roll_pointer指针,通过这个指针可以找到该记录修改前的记录

    通过roll_pointer指针可以将记录的多个版本连接成一个链表,这个链表就是记录的版本记录,每次需要历史版本的数据可以通过当前版本和undo log计算出来

    Read view

    虽然通过构建版本链,可以找到记录的历史版本,但是历史版本那么多,哪个版本才是要读的数据呢?这个时候就需要视图大显身手,通过视图来进行版本可见性判断

    对于读未提交的事务来说,可以读到未提交的事务修改的记录,所以直接读取记录的最新版本就行;对于串行化隔离级别来说,需要使用加锁的方式来访问记录。对于读提交和可重复读的事务来说,需要使用Read view来进行判断哪个版本是当前事务可见的。

    InnoDB为每个事务构造了一个数组,用来保存这个事务启动瞬间,当前正在“活跃”的所有事务ID。“活跃”指的就是,启动了但还没提交。

    Read view主要结构:

    • m_ids:表示创建ReadView时活跃的读写事务列表
    • m_low_limit_id:表示⽣成ReadView时系统中应该分配给下⼀ 个事务的id值,事务ID大于等于该值的数据修改不可见
    • m_up_limit_id:m_ids中的最小值,事务ID小于该值的数据修改可见

    可见性判断:

    1. 如果记录trx_id小于m_up_limit_id或者等于m_creator_trx_id,表明ReadView创建的时候该事务已经提交,记录可见
    2. 如果记录的trx_id大于等于m_low_limit_id,表明事务是在ReadView创建后开启的,其修改,插入的记录不可见
    3. 当trx_id在m_up_limit_id和m_low_limit_id之间的时候,如果id在m_ids数组中,表明ReadView创建时候,事务处于活跃状态,因此记录不可见。

    总结

    MVCC指的就是在使⽤READ COMMITTD、REPEATABLE READ这两种隔离级别的事务在执⾏普通的SEELCT操作时访问记录的版本链的过程,这样⼦可以使不同事 的读-写、写-读操作并发执⾏,从⽽提升系统性能。

    RC和RR这两个隔离级别不同的地方在于:

    • 在可重复读隔离级别下,只需要在事务开始的时候创建一致性视图,之后事务里的其他查询都共用这个一致性视图;
    • 在读提交隔离级别下,每一个语句执行前都会重新算出一个新的视图。

    参考

    淘宝数据库内核月报

    美团技术团队——Innodb中的事务隔离级别和锁的关系

    极客时间mysql45讲

  • 相关阅读:
    poj 3378 Crazy Thairs 夜
    1487. Chinese Football 夜
    容斥原理
    Dancing Links
    三角剖分
    模线性方程模板
    模线性方程
    容斥原理 POJ2773
    DNA Sequence [矩阵]
    hdu 2588 容斥
  • 原文地址:https://www.cnblogs.com/skylv/p/13432951.html
Copyright © 2011-2022 走看看