商丘家具网站建设,建设银行住房租赁品牌,网站建设服务商,抖音代运营怎么样MVCC的全称是Multiversion Concurrency Control(多版本并发控制器)#xff0c;是一种事务隔离级别的无锁的实现方式#xff0c;用于提高事务的并发性能#xff0c;即事务隔离级别的一种底层实现方式。
在了解MVCC之前#xff0c;我们先来回顾一些简单的知识点#xff1a;…MVCC的全称是Multiversion Concurrency Control(多版本并发控制器)是一种事务隔离级别的无锁的实现方式用于提高事务的并发性能即事务隔离级别的一种底层实现方式。
在了解MVCC之前我们先来回顾一些简单的知识点数据库的隔离级别和并发场景。
数据库的隔离级别
主要用来解决多个事务在并发的情况下对同一个数据进行读写操作所产生的一些列线程不安全的问题。
脏读 – 读未提交RU 事务A读取到了事务B还未提交的数据。 不可重复读 – 读已提交RC 事务A读取到事务B已经提交的数据可以解决脏读问题但会出现不可重复读。 可重复读RR 同一是事务下事务在执行期间多次读取同一数据时能够保证读取到的数据是一致的可以解决不可重复读问题但在事务读取过程中如果有另外一个新事务新增/变更会出现幻读。 串行化serializable 最高的隔离级别在该级别下事务串行化顺序执行可以避免脏读幻读和不可重复读的问题但是这种事务隔离级别效率最低比较耗费数据库性能。
读已提交
解决脏读问题为什么不使用行锁如果我们在事务一中对数据进行修改操作时给数据添加一个行锁那么接下来的事务中想要执行SQL语句进行查询操作那么该操作将会被阻塞直到修改操作执行完毕行锁被解开为止如此一来就会降低并发性。
三种并发场景
读 - 读 不存在线程安全问题不需要关心并发 读 - 写 有线程安全问题可能会存在数据更新丢失的问题比如第一类更新丢失第二类更新丢失 第一类更新丢失事务A回滚时将已经提交的事务B更新的数据覆盖了 第二类更新丢失事务A提交覆盖了事务B已经提交的数据造成事务B所做的操作丢失 什么是MVCC
定义
即多版本并发控制是一种并发控制的方法一般在数据库管理系统中实现对数据库的并发访问在编程语言中实现事务内存。
目的
在最早的数据库系统中只有读 - 读之间可以并发读 - 写、写 - 写之间都要阻塞。在引入多版本并发控制技术之后只有写 - 写之间相互阻塞其他三种操作都可以并行这样就达到了提高InnoDB引擎并发度的目的。
实现
在MySQL的内部实现中InnoDB是通过undo log实现undo log可以找回数据的历史版本。找回的历史版本可以提供给用户读按照隔离级别定义有些读请求只能看到比较老的数据版本也可以在回滚的时候覆盖数据页上的数据在InnoDB内部中会记录一个全局的活跃读写事务数据组其主要用来判断事务的可见行
MVCC的三个关键点
MVCC是如果无锁地实现事务的隔离级别的呢主要就是靠以下三个关键因素
隐藏列
在数据库表单中除了我们创建的原数据的列外数据库帮我们维护的三个看不到的隐藏列DB_TRX_ID(事务ID),DB_TRX_ID(存储旧的事务的指针),(ROW_ID)
undo log
回滚实现
通过两个隐藏列trx_id最近一次提交事务的ID和roll_pointer上个版本的地址建立一个版本链。并在事务中读取的时候生成一个Read View读视图在Read Committed隔离级别下每次读取都会生成一个读视图而在Repeatable Read隔离级别下只会在第一次读取时生成一个读视图 ReadView
定义
不加锁的select就是快照读即不加锁的非阻塞读。快照读的前提是非serializable隔离级别在该隔离级别下快照读会退化为当前读之所以出现快照读是基于高并发性能的考虑快照读的实现是基于MVCC的可以认为MVCC是行锁的变种但是他在很多情况下避免了加锁操作降低了开销。因为多版本的原因导致快照读可能读取到的不一定是数据的最新版本而有可能是历史版本
当前读和快照读与MVCC关系
MVCC可以理解为是一个“维护数据的多个版本使得读写操作没有冲突”的概念是一种理想状态。而在MySQL中快照读就是实现MVCC理想模型的其中一个具体的非阻塞读功能而相对而言当前读就是一个悲观锁的具体功能实现
具体实现判断顺序
存储三条数据creator_trx_id当前事务IDmin_trx_id(当前未提交的事务的ID)max_trx_id(未开始的事务)
首先通过undolog拿到最新版本的数据最新一次修改本条数据的事务ID第一次判断将当前事务ID与最新一次修改本条数据的事务ID进行比较 二者相等–本条版本的数据是在当前事务中保存的–该条数据可以读取二者不相等则不能直接拿到该值继续进行判断 第二次判断比较最新一次修改本条数据的事务ID和最小的事务ID 小于–当前版本数据是在事务开始之前保存的–该条数据可以读取到大于等于–不能直接拿到该值继续进行判断 第三次判断比较最新一次修改本条数据的事务ID和最大的事务ID 大于–当前版本的数据是在本事务开始之后保存的–本数据不能被读取–顺着指针找到上一个版本的数据 第四次判断比较最新一次修改本条数据的事务ID是否在最小事务ID和最大事务ID之间 存在于二者之间–当前版本的数据是在未提交的并发事务中 如果事务隔离级别是读已提交–该条数据不能被读取 不存在于二者之间–沿着指针找到上一个版本的数据再进行以上四次判断