专栏首页chenchenchenMVCC多版本并发控制

MVCC多版本并发控制

什么是MVCC

全称Multi-Version Concurrency Control,即多版本并发控制,解决读—写冲突的无锁并发控制。

当前读是一种加锁操作,是悲观锁。同一行数据平时发生读写请求时,会上锁阻塞住。

但mvcc用更好的方式去处理读—写请求,发生读—写请求冲突时不用加锁,提高数据库的并发性能,具体实现就是快照读。

MVCC维护多版本数据,为每个数据修改保存一个版本,版本与事务时间戳相关联。

因为myIsam不支持事务,MVCC都针对InnoDB引擎来讲。

当前读、快照读区别

当前读

它读取的数据库记录,都是当前最新版本,会对当前读取的数据进行加锁,防止其他事务修改数据。是悲观锁的一种操作。

如下操作都是当前读:

  • select lock in share mode (共享锁)
  • select for update (排他锁)
  • update (排他锁)
  • insert (排他锁)
  • delete (排他锁)
  • 串行化事务隔离级别

快照读

快照读的实现基于多版本并发控制。MVCC为事务分配单向增长时间戳,为每个数据修改保存一个版本,版本与事务时间戳相关联

读操作只读取该事务开始前数据库快照

如下操作是快照读:

  • 不加锁的select操作(注:事务级别不是串行化)

MVCC解决什么并发问题

数据库并发场景

  • 读-读:不存在任何问题,也不需要并发控制
  • 读-写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读
  • 写-写:有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失

解决读写冲突

  • 并发读-写时:可以做到读操作不阻塞写操作,同时写操作也不会阻塞读操作。
  • 解决脏读幻读不可重复读等事务隔离问题,但不能解决上面的写-写 更新丢失问题。

因此有了下面提高并发性能的组合拳

  • MVCC + 悲观锁:MVCC解决读写冲突,悲观锁解决写写冲突
  • MVCC + 乐观锁:MVCC解决读写冲突,乐观锁解决写写冲突

MVCC的实现原理

基于版本链undo日志Read View来实现。

版本链

数据库中的每行数据,还有几个隐藏字段,分别是最近修改事务db_trx_id、回滚指针db_roll_pointer

  • db_trx_id 最近修改(修改/插入)事务ID:记录创建这条记录/最后一次修改该记录的事务ID
  • db_roll_pointer 回滚指针,用于配合undo日志,指向这条记录上一个版本(存储于rollback segment里)
  • db_row_id是隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以db_row_id产生一个聚簇索引
  • 删除标识flag, 记录被更新删除并不代表真的删除,而是删除flag变了

每次对数据库记录进行改动,都会记录一条undo日志,每条undo日志也都有一个生成该版本时对应的事务id以及回滚指针(INSERT操作对应的undo日志没有该属性,因为该记录并没有更早的版本)。

随着更新次数的增多,所有的版本都会被roll_pointer属性连接成一个链表,我们把这个链表称之为版本链,版本链的头节点就是当前记录最新的值。如下图一样:

undo log日志

Undo log 主要用于记录数据被修改之前的日志,在表信息修改之前先会把数据拷贝到undo log里。

事务进行回滚时可以通过undo log 里的日志进行数据还原

Undo log 的用途

  • 保证事务进行rollback时的原子性和一致性,当事务进行回滚的时候可以用undo log的数据进行恢复
  • 用于MVCC快照读的数据,在MVCC多版本控制中,通过读取undo log历史版本数据可以实现不同事务版本号都拥有自己独立的快照数据版本

undo log主要分为两种:

  • insert undo log 代表事务在insert新记录时产生的undo log , 只在事务回滚时需要,并且在事务提交后可以被立即丢弃
  • update undo log(主要) 事务在进行update或delete时产生的undo log ; 不仅在事务回滚时需要,在快照读时也需要; 所以不能随便删除,只有在快速读或事务回滚不涉及该日志时,对应的日志才会被purge线程统一清除

Read View(读视图)

Read View主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个Read View读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。

Read View几个属性

  • trx_ids: 当前系统活跃(未提交)事务版本号集合。(当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以越新的事务,ID值越大)。
  • low_limit_id: 创建当前read view 时,当前系统最大事务版本号+1。
  • up_limit_id: 创建当前read view 时,系统正处于活跃事务最小版本号
  • creator_trx_id: 创建当前read view的事务版本号。

Read View可见性判断条件

  • db_trx_id < up_limit_id || db_trx_id == creator_trx_id(显示) 如果数据事务ID小于read view中的最小活跃事务ID,则可以肯定该数据是在当前事务启之前就已经存在了的,所以可以显示。 或者数据的事务ID等于creator_trx_id ,那么说明这个数据就是当前事务自己生成的,自己生成的数据自己当然能看见,所以这种情况下此数据也是可以显示的。
  • db_trx_id >= low_limit_id(不显示) 如果数据事务ID大于read view 中的当前系统的最大事务ID,则说明该数据是在当前read view 创建之后才产生的,所以数据不显示。如果小于则进入下一个判断
  • db_trx_id是否在活跃事务(trx_ids)中
    • 不存在:则说明read view产生的时候事务已经commit了,这种情况数据则可以显示
    • 已存在:则代表我Read View生成时刻,你这个事务还在活跃,还没有Commit,你修改的数据,我当前事务也是看不见的。

Read View和事务隔离级别

Read View用于支持RC(Read Committed,读提交)和RR(Repeatable Read,可重复读)隔离级别实现

RR、RC生成时机

  • 读提交RC隔离级别下,每个快照读都会生成并获取最新Read View,在RC级别下的事务中可以看到别的事务提交的更新。
  • 可重复读RR隔离级别下,同一个事务中第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View,所以一个事务的查询结果每次都是一样的,对之后的修改不可见。

解决幻读问题

  • 快照读:通过MVCC来进行控制的,不用加锁。按照MVCC中规定的“语法”进行增删改查等操作,以避免幻读。
  • 当前读:通过next-key锁(行锁+gap间歇锁)来解决问题的。

参考:

通俗易懂数据库MVCC讲解:https://mp.weixin.qq.com/s/oOL4yradD5w73VsrfoyneA

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [MySQL] MVCC 多版本并发控制实现的事务

    1.没有一个统一的实现标准,实现了非阻塞的读操作,写操作也只锁定必要的行 2.通过保存数据在某个时间点的快照实现的 3.典型的有乐观并发控制和悲观并发控制 4....

    陶士涵
  • MySQL的多版本并发控制(MVCC)

    多版本并发控制技术的英文全称是 Multiversion Concurrency Control,简称 MVCC。

    好好学java
  • MySQL的多版本并发控制(MVCC).

    快照读(SnapShot Read) 是一种一致性不加锁的读,是 InnoDB 并发如此之高的核心原因之一。

    JMCui
  • PostgreSQL中的多版本并发控制-MVCC

    MVCC , Multi - Version Concurrency Control , 多版本控制并发

    小徐
  • PostgreSQL中的多版本并发控制-MVCC

    MVCC , Multi - Version Concurrency Control , 多版本控制并发

    小徐
  • 数据库多版本并发控制MVCC

    多版本并发控制(Multi-Version Concurrency Control, MVCC)是 MySQL 的 InnoDB 存储引擎实现隔离级别的...

    用户6182664
  • MySQL MVCC(多版本控制)

    MySQL 提供了两种事务型的存储引擎:InnoDB 和 NDB Cluster 。另外还有一些第三方存储引擎也支持事务

    双鬼带单
  • MySQL MVCC(多版本控制)

    1. MySQL 中的事务 MySQL 提供了两种事务型的存储引擎:InnoDB 和 NDB Cluster 。另外还有一些第三方存储引擎也支持事务 1. My...

    双鬼带单
  • MySQL多版本并发控制机制(MVCC)-源码浅析

    作为一个数据库爱好者,自己动手写过简单的SQL解析器以及存储引擎,但感觉还是不够过瘾。<<事务处理-概念与技术>>诚然讲的非常透彻,但只能提纲挈领,不能让你玩转...

    无毁的湖光-Al
  • MySQL多版本并发控制机制(MVCC)-源码浅析

    作为一个数据库爱好者,自己动手写过简单的SQL解析器以及存储引擎,但感觉还是不够过瘾。<<事务处理-概念与技术>>诚然讲的非常透彻,但只能提纲挈领,不能让你玩转...

    呆呆
  • MySQL 事务隔离级别和多版本并发控制MVCC

    MySQL 提供了两种事务型的存储引擎:InnoDB 和 NDB Cluster 。另外还有一些第三方存储引擎也支持事务

    双鬼带单
  • MySQL - 多版本控制 MVCC 机制初探

    MySQL InnoDB 存储引擎,实现的是基于多版本的并发控制协议——MVCC,而不是基于锁的并发控制。

    小小工匠
  • MySQL专题 - 多版本并发控制 MVCC & read committed 隔离级别

    settransaction isolation level read committed;setautocommit=0;begin;

    用户1081422
  • SQL Server 2008多版本并发控制

    数据库的一致性,也是衡量DBMS性能的重要指标之一。目前大多数商业数据库(DB2, SQL Server)的并发控制采用的是两阶段锁(Two-Phase Loc...

    张善友
  • SQL优化(六) MVCC PostgreSQL实现事务和多版本并发控制的精华

    Jason Guo
  • MySQL是怎么读数据的——多版本并发控制

    我在之前的文章中(【MySQL入门】之MySQL数据库的锁机制(一),【MySQL入门】之MySQL数据库的锁机制(二))介绍了MySQL的全局锁、表锁和行锁,...

    MySQL数据库技术栈
  • 浅谈MySQL并发控制:隔离级别、锁与MVCC

    如果数据库中的事务都是串行执行的,这种方式可以保障事务的执行不会出现异常和错误,但带来的问题是串行执行会带来性能瓶颈;而事务并发执行,如果不加以控制则会引发诸多...

    程序员小高
  • 值得收藏,揭秘 MySQL 多版本并发控制实现原理

    MySQL 中多版本并发控制(MVCC),是现代数据库引擎实现中常用的处理读写冲突的手段,MVCC 作为 MySQL 高级应用特性,目的在于提高数据库高并发场景...

    架构精进之路
  • webpack多版本控制方案

    项目中有这么一个需求,就是按需启动mock功能。考虑到mock只是在特定情况下,所以考虑通过 cross-env 来处理。

    神葳

扫码关注云+社区

领取腾讯云代金券