MVVC学习的一点理解

MVVC学习的一点理解MVCC全名叫做:多并发版本并行(concurrent)控制是一种并发控制方法再MySQLInnoDB的实现主要是为了提高数据库并发性能,处理读-写冲突MVCC知识一个抽象概念,而在MySQL中,快照读就是MySQL实现MVCC模型的一个非阻塞读功能(相对而言,当前读就是悲观锁的具体实现)

大家好,欢迎来到IT知识分享网。

MVCC

全名叫做:多并发版本并行(concurrent)控制

是一种并发控制方法

再MySQL InnoDB的实现主要是为了提高数据库并发性能,处理读-写冲突

MVCC知识一个抽象概念,而在MySQL中,快照读就是MySQL实现MVCC模型的一个非阻塞读功能(相对而言,当前读就是悲观锁的具体实现)

当前读和快照读

  • 当前读:加悲观锁

    • select lock in share mode

    • select for update

    • update/insert/delete

  • 快照读

    • 不加锁的select就是快照读,即不加锁的非阻塞读

    • 快照读的实现是基于MVCC(可以认为其是行锁的一个变种,很多情况下避免了加锁操作)

    • 由于是基于多版本,快照读读到的并不一定是数据的最新版本,而有可能是历史版本

MVCC的能解决的问题

数据库并发三种场景

  • 读-读:不需要并发控制

  • 读-写:隔离性问题,脏读,幻读,不可重复读

  • 写-写:可能存在更新丢失问题,需要加悲观锁或者乐观锁

 

MVCC就是用来解决读-写冲突的无锁并发控制

  • 为事务分配单项增长的时间戳,为每个修改保存一个版本

  • 版本与事务时间戳关联,读操作只读事务开始前数据库的快照

  • 可以解决脏读,幻读,不可重复读等读写隔离问题,但是不能解决更新丢失问题(写写隔离)

MVCC的实现原理

其实现大概依赖三部分

  • 3个隐式字段:每一行除了用户自定义的字段外,还有数据库隐式定义的,用来记录事务的时间戳

    • DB_TRX_ID:最近一次修改这条记录的事务ID

    • DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本(指向undo日志里)

    • DB_ROW_ID:隐含的自增id(隐藏逐渐),如果没有主键,InnoDB会自动以这个字段产生一个聚簇索引

  • undo日志:主要分为两种

    • 插入undo日志,事务提交之后就可以丢掉的,因为没有读写冲突,这部分只负责事务回滚

    • update undo日志,包括update和delete,因为有读写冲突,所以还要另外负责处理读写冲突

  • Read View:读视图,其实就是所谓的快照

    • 每个事务在开启的时候都会被分配一个id(自增)

    • 在事务进行快照读的时候产生Read View,记录并维护系统当前活跃事务的id

    • Read View主要是用来做可见性判断的,执行快照读的时候来判断当前事务能看到哪个版本的数据,有可能是最新版本,也有可能是undo log中某个旧版本

    • 维护四个内容

      • id_list生成快照时,系统中活跃的事务id列表

      • m_trx_id:当前活跃事务最小的id

      • max_trx_id:下一个将要分配的事务id

      • creator_trx_id:声称该ReadView事务的事务id

 

 

第一次快照读某个数据的时候生成Read View(快照),然后之后每次再读取这行数据的时候,都会根据之前生成的这个快照来判断版本号,确定哪个版本是可读的,哪个版本是不可读的

 

当某个事务想要读取某一行数据时,MVCC判断哪个版本对当前事务是可见的过程:

  • 从版本链开始获取记录,记为id(查每行记录的DB_TRX_ID,看最后一次修改这行数据的事务)

  • 如果这个id==creator_trx_id,说明上一次修改是本事务,可以直接读取

  • 如果这个id<min_trx_id,说明上一次修改这行数据的事务已经被提交了(或者说成生成这个版本的时间在生成快照之前),这个版本可以被当前事务访问

  • 如果这个id>=max_trx_id,说明上一次修改这行数据的事务在生成Read View之后才开启,这个版本不可以被当前事务访问(否则会造成不可重复读),需要根据链表指针,找到下一个版本,重复这个步骤

  • 最后还要查一下是否在活跃事务列表里(因为这个事务可能加载一大一小之前,但是很早之前就commit了,生成快照的时候不活跃,和<min_trx_id的情况是一样的),如果在列表里,说明这个版本是不可访问的,因为这是其他事务未提交的数据

 

附一张流程图吧

MVVC学习的一点理解

 

总结一下,事实上快照就相当于记录了一下快照读时各个事务的状态,记录了两个边界情况和一个活跃队列,目的都是为了定位后面读取时的版本号和当前事务的相对时间关系,而版本号的表示是通过最后一次修改该行的事务id和它之后的那条链表

  • 如果在生成快照的时候已经提交了,当然没问题,这包括两种情况,小于最小id和不在活跃队列中都是这个情况(我认为最小id是为了减小检查这个list的次数)

  • 如果在生成快照的时候还未提交(查版本号找到的最近一次修改该行的事务id发现的),就需要查找undo log上一条记录,直到查找到合适读的版本号

 

再加一点:

MVVC是用来解决读写隔离的,读写隔离有四个等级,串行化是使用了行锁,读取未提交没有做读写隔离

  • read-committed:每次读取的时候都生成Read View,所以可能导致不可重复读

  • repeatable read:每次读取都根据第一次快照读的Read View,所以每次都是读取到同一个版本号

 

参考自:https://blog.csdn.net/zzti_erlie/article/details/110454543?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166761746016800182734227%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166761746016800182734227&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-2-110454543-null-null.142^v63^opensearch_v2,201^v3^control_2,213^v1^control&utm_term=MVCC&spm=1018.2226.3001.4187

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30376.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信