关键词:事务,ACID,隔离级别,MVCC,共享锁,排它锁

阅读本文前请先阅读http://hedengcheng.com/?p=771 http://www.hollischuang.com/archives/943

本文意在弄清楚这些概念间的关系及其作用。弄清Mysql在开启事务的情况下,每条sql执行时的加锁操作和MVCC版本控制。为使讨论简单,本文忽略了GAP锁(间隙锁、范围锁)。

我们经常所高并发,高可用。就是从来评估,任何事物都可以从这两个角度来分析。在Mysql数据库中,事务就是用来保证的,MVCC就是用来保证的。

事务

我们使用事务来保证每一条SQL语句的结果执行符合我们的预期。我们说事务必须具备ACID特性。ACID中的三者:原子性、一致性和持久性其实描述的都差不多,保证SQL执行结果的可靠性。而隔离性就比较复杂了,隔离性描述的是在并发场景下数据库的表现,但并发量并不是固定的,而不同的业务可能有不同的需求,为了使数据库能适应不同的并发场景,所以伟大的人们又定义了四种隔离级别:Read Uncommited,Read Committed (RC),Repeatable Read (RR),Serializable。随着数据库隔离级别的提高,数据的并发能力也有所下降。

隔离级别

标准隔离级别下数据库会怎么表现可参考http://www.hollischuang.com/archives/943,我们这里只讨论共享锁排它锁这两概念,读加共享锁,写加排它锁:

在RC隔离级别下,修改数据会加排它锁,事务结束释放,其他事务不许读,解决脏读问题。(共享锁当场释放)

在RR隔离级别下,读数据加共享锁,事务结束释放,其他事务不许修改,解决不可重复读(共享锁事务结束释放)

实际上都把操作串行化了。而Mysql对其进行了优化,一个事务读时其他事务不能写,一个事务写时其他事务不能读?我不这么干照样能解决脏读和不可重复读问题。MVCC出现了。(这也使得问题变得越来越复杂,而不一样的地方也开始出现在RR隔离级别下,碰巧Mysql的默认隔离级别就是RR)

MVCC

MVCC即多版本并发控制,使用了双版本号来解决数据的隔离问题。(“create”一个版本号,“delete”一个版本号,修改操作拆分为“delete”和“create”)每个事务在开始对每张表增删改查操作时都会生成一个版本号,每个事务只能查到“create”小于本版本号和“delete”大于本版本号的数据。这样,增删查操作就完全可以并发进行了,只有修改操作是一定要排队的。这样,就算没有共享锁也解决了不可重复读问题,因为其他事务修改后,数据的版本号比我大,我不会读到。

MVCC在RR隔离级别下的并发

引入MVCC之后,看似很美好。然而大家有没有想过两个事务先后对一条数据做更新操作,然后两个事务再读取那条数据,分别读到什么?哈哈,这根本是不可能出现的,因为修改操作是串行的,另一个事务必须先commit本事务才能修改。好,换个问题,两个事务先后对一条数据做+1操作,另一个事务提交后,本事务再+1,再读取那条数据,本事务是读取到+1还是+2的结果?如果读取到+2,那不是破坏了隔离性,读到了其他事务提交的数据么?

然而事实确实是这样,其他事务已经提交,本事务也已修改过那条数据了,之后当然要读到+2才行。虽然本来是0,本事务明明只加了1,可读取后却变成2了,有点不适应。确实,在标准的RR隔离级别下,因为操作都是串行的,本事务读取一行数据后,其他事务就不能修改这条数据了,这条数据永远只有本事务在操作,所以严格满足隔离性。但是Mysql的RR增强了读与写的并发,只有当两个事务同时修改一条数据需要串行,其他所有操作都可以并行。所以造成了这种结果,好像出现了不可重复读。但是这种不可重复读实际上是符合我们的直观感受的,在本事务对数据修改后,当然要读取到最新的数据。

要对其过程进行分析的话:

  • 数据create版本号为0
  • 事务1版本号为1,读取数据value=0
  • 事务2版本号为2,修改数据value+1=1,原数据delete版本号为2,新数据create版本号更新为2,commit
  • 事务1修改数据value+1=2,(由于修改是当前读,永远读取版本号最大的数据,所以读取到value为1)修改后delete版本号为1,新数据create版本号为1
  • 本事务读取数据value=2

深入分析:

其实上面的描述也是有漏洞的,如果有第三个事务版本号为3呢?因为版本号为3,是不是可以直接读取事务1、2未提交的数据?实际上在MVCC中,每个事务还有一个最低可见版本low_limit_id(事务号 >= low_limit_id的记录,对于当前事务都是不可见的),把当前正在执行还没commit的事务给过滤掉了。例如事务3,虽然版本号为3,但是low_limit_id=1,所以事务1和事务2的修改对3都是不可见的。

总结

为了解决隔离性问题,都没有使用完全copy数据这种笨方法。传统数据库使用共享锁和排它锁使读写操作串行;Mysql使用MVCC和排它锁,读写可并行。Mysql在RR隔离级别以下,和传统方式表现一致,在RR隔离级别,和传统方式有差异,体现在本事务更新某条数据后,能读取到其他事务对该条数据已提交的修改。

Mysql隔离级别,锁与MVCC的更多相关文章

  1. MYSQL隔离级别 与 锁

    1.四种隔离级别下数据不一致的情况   脏读 不可重复读 幻读 RU 是 是 是 RC(快照读) 否 是 是 RC(当前读) 否 否 是 RR(快照读) 否 否 是 RR(当前读) 否 否 否 Ser ...

  2. 详解MySQL隔离级别

    一个事务具有ACID特性,也就是(Atomicity.Consistency.Isolation.Durability,即原子性.一致性.隔离性.持久性),本文主要讲解一下其中的Isolation,也 ...

  3. MySQL事务及事务隔离级别 锁机制

    什么是事务? 当多个用户访问同一份数据时,一个用户在更改数据的过程中可能有其他用户同时发起更改请求,为保证数据库记录的更新从一个一致性状态更改为另一个一致性状态,这样的操作过程就是事务.事务具有的AC ...

  4. mysql 隔离级别与间隙锁等

    数据库隔离级 SQL标准中DB隔离级别有: read uncommitted:可以读到其它transaction 未提交数据 read committed:可以读到其它transaction 已提交数 ...

  5. mysql 隔离级别与锁

    1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约 ...

  6. mysql隔离级别与锁,接口并发响应速度的关系(2)

    innoDB默认隔离级别 mysql> SELECT @@tx_isolation; +-----------------+ | @@tx_isolation | +-------------- ...

  7. mysql隔离级别与锁,接口并发响应速度的关系(1)

    默认隔离级别:可重复读 原始数据 | id | name | addr | | nick | NULL | 事务1 事务2 start transaction start transaction ; ...

  8. mysql隔离级别

    MySQL/InnoDB定义的4种隔离级别: Read Uncommited 可以读取未提交记录. Read Committed (RC) 针对当前读,RC隔离级别保证对读取到的记录加锁 (记录锁), ...

  9. Mysql隔离级别 sql示例理解

    前言 事务要解决的是多线程并发修改数据库的问题.Mysql innodb 引擎支持事务.类似 Java 中的各种锁,例如乐观锁(CAS),读写锁,悲观锁.事务也有很多级别. 每个隔离级别要解决的问题都 ...

随机推荐

  1. Jrebel简单的热部署一个web工程

    前言:博主最近在做Hybris开发,漫长的启动时间大大的拖累了项目的进度,而Jrebel的出现就是为了减少项目重启的时间或者说修改了代码后直接不用重启就可以看到修改的结果,但是Hybris的部署一直没 ...

  2. echart异步刷新图表,详细配置注释

    echarts刷新技巧: echartData.chear(); //当异步改变数据时,配合echartData .setOption(option)才会有动画效果 echartData.resize ...

  3. Android 内存暴减的秘密?!

    作者:杨超,腾讯移动客户端开发 工程师  商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. WeTest 导读 在我这样减少了26.5M Java内存! 一文中内存优化一期已经告一段落, ...

  4. 扎实基础之从零开始-Nginx集群分布式.NET应用

    1       扎实基础之快速学习Nginx Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.其特点是占有内存少 ...

  5. vue2.0 关于Vue实例的生命周期

    什么是生命周期 Vue实例有一个完整的生命周期,也就是从开始创建.初始化数据.编译模板.挂载Dom.渲染→更新→渲染.卸载等一系列过程,我们称这是Vue的生命周期.通俗说就是Vue实例从创建到销毁的过 ...

  6. ASP.NET MVC 设置区域默认定向

    public override void RegisterArea(AreaRegistrationContext context) { context.MapRoute( "m_defau ...

  7. docker with flannel

    ** 原创文章,请勿转载 ** docker的单host,多container环境下,是使用host的docker0网桥进行通信的.如果跨host, container之间要通信怎么办呢?答案是fla ...

  8. 【转载】MySQL之权限管理

    一.MySQL权限简介 关于mysql的权限简单的理解就是mysql允许你做你全力以内的事情,不可以越界.比如只允许你执行select操作,那么你就不能执行update操作.只允许你从某台机器上连接m ...

  9. 大白话说Java泛型(一):入门、原理、使用

    文章首发于[博客园-陈树义],点击跳转到原文<大白话说Java泛型(一):入门.原理.使用> 远在 JDK 1.4 版本的时候,那时候是没有泛型的概念的.当时 Java 程序员们写集合类的 ...

  10. es6的常用语法

    最常用的ES6特性 let, const, class, extends, super, arrow functions, template string, destructuring, defaul ...