详解MySQL 数据库隔离级别与MVCC

Mysql是我们日常生产与学习中最常接触到的数据库之一,今天讲一讲在Mysql(或者说其他类似的数据库)中存在的隔离级别以及用来提高效率的多版本并发控制(MVCC)。

一、隔离级别

首先我们需要提到一个概念:事务。什么是事务?事务就是完成一个基础操作的一系列操作语句的一个集合。例如我要将200元从账户A转移到账户B,那么我可能会进行一下的操作:
a.验证账户A中的余额是否大于200元。
b.将账户A中的余额减200元。
c.将账户B中的余额加200元。
我们就将上面的abc三个操作成为一个事务。
这时,我们会注意到我们所说的一个事务有可能是由多条语句组合而成的,而事务又存在原子性,即事务的执行过程中是不能被打断的,这就带来一个问题,如果在这三步执行过程中有另外的语句插入进来执行,是否会对结果产生影响,因为此时破坏了事务的原子性。而这种插入的情况在并发的环境下是十分常见的。因此,我们(或者说是数据库引擎)就需要在一个事务的执行过程中对它进行“保护”,即保证外界的其他事务的语句不能随意的插进正在执行的事务语句之中,来保证事务的正常执行。这时候我们很容易的会想到“加锁”这个方法。这其实是一种很笼统的说法,因为加锁虽然能够保证事务的正常执行,但是却会带来较大的额外开销,因此合适的时候选择合适的加锁方式对查找效率的影响就非常大。而“锁”得严不严,就区分除了集中不同的隔离级别。

READ UNCOMMITED(读未提交)

这种隔离界别下,读取数据的时候不受任何影响。即你甚至可以读取一个正在被其他事务修改的数据,想读就读,想改就改。这当然开销很小,但是会带来许多的问题,比如“脏读”。即读取到了正在修改但是却还没有提交的数据,这就会造成数据读取的错误。从性能上来说,READ UNCOMMITED不会比其他级别好太多,但是却带来了非常多的麻烦的问题,因此在实际中很少使用这个个立即被。

READ COMMITED(提交读/不可重复读)

这个级别在READ UNCOMMITED的基础上添加了一些规定,是一些数据库的默认隔离级别。它与READ UNCOMMITED的区别在于,它规定读取的时候读到的数据只能是提交后的数据。举个例子,数据a在上一次提交之后的值是1,这时候有一个线程进来对a进行修改,将a修改为2,但是此时并未提交事务(COMMIT),在这种情况下,READ UNCOMMITED级别下读取到的a的值就是当前的2,但是READ COMMITED级别下读取到的还是上一次提交之后的值,即a为1,必须到修改线程将a的值变为2这个事务提交之后读取到的a的值才是2。这个级别所带来的问题就是不可重复读。即上一个时间读取到的a的值是1,但是随着修改线程对事务的提交,a的值变为了2,这时候读到的值就是2了,即执行两次相同的读取操作得到的值却不一样。
不可重复读同脏读的区别在于,脏读是一个事务读取了另一未完成的事务执行过程中的数据,而不可重复读是一个事务执行过程中,另一事务提交并修改了当前事务正在读取的数据。

REPEATED READ(可重复读)

REPEATED READ在READ COMMITED的基础上又添加了一些约束性的规则,它也是MySQL数据库的默认隔离级别。简单来说就是在一个事务的执行期间禁止其他事务对相应的数据进行修改,这就彻底使得一个事务的执行过程中所查询到的数据一定是一致的,即解决了脏读和不可重复读的问题,但是却带来了新的问题,即“幻读”。
“幻读”指的是在一个事务执行过程中虽然禁止了对相应数据的修改,但是其他的事务依然可以插入数据,这时候第一个事务就会发现会“莫名其妙”多出来一些数据,像是出现了幻觉似的。幻读和不可重复读都是读取了另一条已经提交的事务(这点同脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

SERIALIZABLE (可串行化)

这是最严格的一个隔离级别。它通过强制事务串行执行,避免了幻读的问题。但是这种隔离级别的开销极大,一般也不常使用。

各种隔离级别与可能的问题关系如下:

隔离级别 脏读 不可重复读 幻读 加锁
READ UNCOMMITED YES YES YES NO
READ COMMITED NO YES YES NO
REPEATED READ NO NO YES NO
SERIALIZABLE NO NO NO YES

二、MVCC

试想一下,如果每次SQL操作为了保证数据的一致性与准确性,都需要加一个行级锁的话,非常可靠,但是带来的系统开销与查找效率的下降也是非常明显的,因此MVCC就是为了解决这种矛盾而产生的。
首先MVCC会在表中的每一行记录后面保存两个隐藏的列,一个保存行的创建时间,一个保存行的过期(删除)时间。这个时间值并不是真的时间,而是一个系统版本号。事务开始的时刻的系统版本号作为事务的版本号,用来和查询到的每行记录的版本号进行比较。

  • INSERT:为新插入的每一行保存当前的系统版本号作为行版本号。
  • DELETE:为删除的每一行保存当前的系统版本号最为行删除版本号。
  • UPDATE:更新其实应该理解为插入一条新的数据,并删除原来数据的过程,即为新插入的数据保存当前的系统版本号作为行版本号,并为删除的数据保存当前的系统版本号作为删除版本号。
  • SELECT:只查询满足下列条件的行:

a.行版本号小于等于事务版本号
b.删除版本号未定义或者大于事务版本号

保存了这两个版本号之后绝大多数的操作都可以在不加锁的情况下进行正确的操作,保证了性能和效率。
值得注意的是MVCC只在READ COMMITED和REPEATABLE READ两个隔离级别下工作。

以上就是详解MySQL 数据库隔离级别与MVCC的详细内容,更多关于MySQL 数据库隔离级别与MVCC的资料请关注我们其它相关文章!

(0)

相关推荐

  • 关于Mysql隔离级别、锁与MVCC介绍

    本文意在弄清楚这些概念间的关系及其作用.弄清Mysql在开启事务的情况下,每条sql执行时的加锁操作和MVCC版本控制.为使讨论简单,本文忽略了GAP锁(间隙锁.范围锁). 我们经常所高并发,高可用.就是从质和量来评估,任何事物都可以从这两个角度来分析.在Mysql数据库中,事务就是用来保证质的,MVCC就是用来保证量的. 事务 我们使用事务来保证每一条SQL语句的结果执行符合我们的预期.我们说事务必须具备ACID特性.ACID中的三者:原子性.一致性和持久性其实描述的都差不多,保证SQL执行结

  • MySQL中的乐观锁,悲观锁和MVCC全面解析

    前言 在数据库的实际使用过程中,我们常常会遇到不希望数据被同时写或者读的情景,例如秒杀场景下,两个请求同时读到系统还有库存1个,然后又先后把库存更新为0,这时候就会出现超卖的情况,这时候货物的实际库存和我们的记录就会对应不上了. 为了解决这种资源竞争导致的数据不一致等问题,我们需要有一种机制来进行保证数据的正确访问和修改,而在数据库中,这种机制就是数据库的并发控制.其中乐观并发控制,悲观并发控制和多版本并发控制是数据库并发控制主要采用的技术手段. 悲观并发控制 本质 维基百科:在关系数据库管理系

  • MySQL事务及Spring隔离级别实现原理详解

    1.事务具有ACID特性 原子性(atomicity):一个事务被事务不可分割的最小工作单元,要么全部提交,要么全部失败回滚. 一致性(consistency):数据库总是从一致性状态到另一个一致性状态,它只包含成功事务提交的结果 隔离型(isolation):事务所做的修改在最终提交一起,对其他事务是不可见的 持久性(durability):一旦事务提交,则其所做的修改就会永久保存到数据库中. 2.事务的隔离级别 1)隔离级别的定义与问题 READ UNCOMMITTED(读未提交):事务的修

  • mysql多版本并发控制MVCC的实现

    事务隔离级别设置 set global transaction isolation level read committed; //全局的 set session transaction isolation level read committed; //当前会话 修改事务提交方式(是否自动提交,mysql默认自动提交) SET AUTOCOMMIT = 1; //自动提交,为0手动提交 不同数据库引擎MVCC模式各不相同,典型有乐观和悲观并发控制. innodb 说明: InnoDB的MVCC

  • mysql、oracle默认事务隔离级别的说明

    1.事务的特性(ACID) (1)原子性(Atomicity).事务中所涉及的程序对数据库的修改操作要么全部成功,要么全部失败. (2)一致性(Consistency).事务执行前和执行后来源和去向保持平衡. (3)隔离性(Isolation).并发时每个事务是隔离的,相互不影响. (4)持久性(Durubility).一旦事务成功提交,应该保证数据的完整存在. 2.事务隔离级别 (1)read uncommitted 未提交读 所有事务都可以看到没有提交事务的数据. (2)read commi

  • 浅析MySQL - MVCC

    版本链 在InnoDB引擎表中,他们的聚簇索引记录中有两个隐藏列: trx_id:用来存储对数据进行修改时的事务id roll_pointer:每次对哪条聚簇索引记录有修改的时候,就会把老版本写入undo日志中.这个roll_pointer就是存了一个指针,它指向这条聚簇索引记录的上一个版本的位置,通过它来获得上一个版本的记录信息. id name trx_id roll_pointer 1 小明 50 0x00af 例如目前有个trx_id是60的事务正执行如下语句: update table

  • 全面解析MySQL中的隔离级别

    数据库并发的对同一批数据进行增删改,就可能会出现我们所说的脏写.脏读.不可重复读.幻读等一系列问题.MySQL提供了一系列机制来解决事务并发问题,比如事务隔离.锁机制.MVCC多版本并发控制机制.今天来探究一下事务隔离机制. 事务是一组SQL组成的逻辑处理单元,先来看下事务的ACID特性: 原子性(Atomicity) :事务是一个原子操作单元,对数据进行修改,要么全执行要么全不执行.是从执行层面上来描述的. 一致性(Consistent) :在事务开始和完成时,数据都必须保持一致状态.是从执行

  • 详解MySQL中事务隔离级别的实现原理

    前言 说到数据库事务,大家脑子里一定很容易蹦出一堆事务的相关知识,如事务的ACID特性,隔离级别,解决的问题(脏读,不可重复读,幻读)等等,但是可能很少有人真正的清楚事务的这些特性又是怎么实现的,为什么要有四个隔离级别. 今天我们就先来聊聊MySQL中事务的隔离性的实现原理,后续还会继续出文章分析其他特性的实现原理. 当然MySQL博大精深,文章疏漏之处在所难免,欢迎批评指正. 说明 MySQL的事务实现逻辑是位于引擎层的,并且不是所有的引擎都支持事务的,下面的说明都是以InnoDB引擎为基准.

  • 聊聊MySQL事务的特性和隔离级别

    网上对于此类的文章已经十分饱和了,那还写的原因很简单--作为自己的理解笔记. 前言   此篇文章作为自己学习MySQL的一些个人理解,使用的引擎是InnoDb.首先先讲讲事务的概念,在<高性能MySQL>第三版中其对事务的描述是这样的: 事务就是一组原子性的SQL查询,或者说一个独立的工作单元.如果数据库引擎能够成功地对数据库应用该组查询的全部语句,那么就执行该组查询.如果其中有任何一条语句因为崩溃或其他原因无法执行,那么所有的语句都不会执行. ​​  换句话说,事务就是一个整体单位,里面的S

  • 详解MySQL 数据库隔离级别与MVCC

    Mysql是我们日常生产与学习中最常接触到的数据库之一,今天讲一讲在Mysql(或者说其他类似的数据库)中存在的隔离级别以及用来提高效率的多版本并发控制(MVCC). 一.隔离级别 首先我们需要提到一个概念:事务.什么是事务?事务就是完成一个基础操作的一系列操作语句的一个集合.例如我要将200元从账户A转移到账户B,那么我可能会进行一下的操作: a.验证账户A中的余额是否大于200元. b.将账户A中的余额减200元. c.将账户B中的余额加200元. 我们就将上面的abc三个操作成为一个事务.

  • 一文详解MySQL不同隔离级别都使用什么锁

    目录 说透 MySQL 锁机制 事务隔离级别 MySQL 锁类型 读未提交 读已提交 可重复读 总结 在上篇文章,我们聊了「MySQL 啥时候会用表锁,啥时候用行锁」这个问题.在文章中,我们还留了一个问题,即:如果查询或更新时的数据特别多,是否从行锁会升级为表锁? 此外,还有朋友留言说到:不同的隔离级别可能会用不同的锁,可以结合隔离级别来聊聊.其实上面虽然是两个问题,但如果你把不同隔离级别下的加锁问题搞清楚了,那么第一个问题自然也清楚了. 今天,就让我带着大家来聊聊不同隔离级别下,都会使用什么锁

  • mysql数据库隔离级别详解

    目录 隔离级别 一.mysql有四个事务隔离级别 二.为什么默认RR隔离级别? 三.RR隔离级别下手动加锁解决幻读理论基础 脏读.不可重复读.幻读 及其解决方法 事务隔离级别命令行操作 操作验证 一.实现脏读 二.操作验证--实现不可重复读 三.操作验证--解决不可重复读 四.操作验证--实现幻读 总结 隔离级别 一.mysql有四个事务隔离级别 每个级别都有字符或数字编号 读未提交 READ UNCOMMITTED | 0 : 存在脏读,不可重复度,幻读的问题. 读已提交 READ COMMI

  • 详解MySQL数据库千万级数据查询和存储

    百万级数据处理方案 数据存储结构设计 表字段设计 表字段 not null,因为 null 值很难查询优化且占用额外的索引空间,推荐默认数字 0. 数据状态类型的字段,比如 status, type 等等,尽量不要定义负数,如 -1.因为这样可以加上 UNSIGNED,数值容量就会扩大一倍. 可以的话用 TINYINT.SMALLINT 等代替 INT,尽量不使用 BIGINT,因为占的空间更小. 字符串类型的字段会比数字类型占的空间更大,所以尽量用整型代替字符串,很多场景是可以通过编码逻辑来实

  • 详解MySQL多版本并发控制机制(MVCC)源码

    目录 一.前言 二.MVCC(多版本并发控制机制) 2.1.Repeatable Read 2.2.Read Commit 2.3.MVCC的优势 三.MVCC(实现机制) 3.1.select运行栈 3.2.read_view的创建过程 3.3.行版本可见性 3.4.undolog搜索可见版本的过程 3.5.read_view创建时机再讨论 四.MVCC和锁的同时作用导致的一些现象 五.总结 一.前言 作为一个数据库爱好者,自己动手写过简单的SQL解析器以及存储引擎,但感觉还是不够过瘾.<<

  • 详解Mysql数据库平滑扩容解决高并发和大数据量问题

    目录 1 停机方案 2 停写方案 3 平滑扩容之双写方案(中小型数据) 4 平滑扩容之2N方案大数据量问题解决 4.1 扩容问题 4.2 解决方案 4.3 双主架构思想 4.4 环境部署 5 数据库秒级平滑2N扩容实践 5.1 新增数据库VIP 5.2 应用服务增加动态数据源 5.3 解除原双主同步 5.4 安装MariaDB扩容服务器 5.5 增加KeepAlived服务实现高可用 5.6 清理数据并验证 1 停机方案 发布公告 停止服务 离线数据迁移(拆分,重新分配数据) 数据校验 更改配置

  • 详解MySQL数据库之触发器

    1 引言 本文是对MySQL中触发器的总结,从触发器概念出发,结合实例对创建触发器.使用触发器.删除触发器进行介绍. 2 触发器简介 MySQL触发器和存储过程一样,都是嵌入到MySQL的一段程序.触发器是由事件来触发某个操作,这些事件包括INSERT.UPDATE.DELETE.如果定义了触发器,当数据库执行这些语句的时候就会激活触发器执行相应的操作,触发程序是与表有关的命令数据库对象,当表上出现特定事件,将激活该对象. 触发器是一个特殊的存储过程,不同的是,执行存储过程要使用call语句来调

  • 详解MySQL 数据库范式

    前言: 关于数据库范式,时常有听说过,一直没有详细去了解.一般数据库书籍或数据库课程会介绍范式相关内容,范式也经常出现在数据库考试题目中.不清楚你是否对范式有比较清晰的了解呢?本篇文章我们一起来学习下数据库范式吧. 1.数据库范式简介 为了建立冗余较小.结构合理的数据库,设计数据库时必须遵循一定的规则.在关系型数据库中这种规则就称为范式.范式是符合某一种设计要求的总结.要想设计一个结构合理的关系型数据库,必须满足一定的范式. 范式的英文名称是 Normal Form ,简称 NF .它是英国人

  • 详解mysql数据库增删改操作

    插入数据 insert into 表名(列名1,列名2,列名3) values(值1,值2,值3); insert into user(user_id,name,age) values(1,'nice',24); 简单写法可以省去字段名,但是要插入全部字段. 批量插入 单条插入和批量插入的效率问题 mysql多条数据插入效率大于单条数据插入 删除记录 delete from 表名 [where 条件] 如果没有指定条件,会将表中数据一条一条全部删除掉. delete删除数据和truncate删除

  • 详解MySQL数据库--多表查询--内连接,外连接,子查询,相关子查询

    多表查询 使用单个select 语句从多个表格中取出相关的查询结果,多表连接通常是建立在有相互关系的父子表上; 1交叉连接 第一个表格的所有行 乘以 第二个表格中的所有行,也就是笛卡尔积 创建一个消费者与顾客的表格: 代码如下: -- create table customers( -- id int primary key auto_increment, -- name VARCHAR(20)not null, -- address VARCHAR(20)not NULL -- ); -- C

随机推荐