我们都知道数据库的事务具有ACID的四个属性:原子性,一致性,隔离性和持久性。然后在多线程操作的情况下,如果不能保证事务的隔离性,就会造成数据的修改丢失(事务2覆盖了事务1的修改结果)、读到脏数据(事务2读到了事务1未回滚的数据)、不可重读(事务2读到了事务1未提交的修改)和幻读(事务2读到了事务1未提交的增删)等。保证事务隔离性可以防止事务出现以上问题,那么数据库又是怎么来保证事务的隔离性的呢?

  mysql使用两阶段协议来保证事务执行的串行化从而保证事务的隔离性的。
  首先,为了保证数据访问的串行,每个数据资源都有对应的锁(mysql的锁只细化到行级),那么只要保证每个数据资源的访问都是串行化的,然后整个数据库不就可以保证每个数据操作之间的隔离性了么,就是说:

  只要每个数据操作都有对应的锁覆盖,然后把每个操作都加上对应的锁,这样可以保证事务执行的串行化么?

  答案是:可以保证,但是有个前提是每个事务只包含对一个数据的操作。事实上mysql也默认是这样做的:如果用户没有手动开启事务,那么根据AUTOCOMMIT机制,mysql默认将每一个数据库操作封装成一个事务来处理。

  然而实际情况中,很多时候一个事务不只包含一个数据库操作,比如电商平台在生成订单时,一个事务里包含了对订单表、用户表、商品表等的操作。在多线程操作的情况下,如果只用数据库的锁来保证的话,就会出现上面所提到的一些数据异常情况。这时候就需要两阶段协议来保证事务的隔离性了。那么进入今天的主题:

  两阶段协议如何保证多事务操作之间的隔离性?

  上面说过,只要事务执行是串行的,事务之间就是隔离的,在网上搜索两阶段协议为何能保证串行化,只搜到一个封锁定理:如果事务是良构的且是两阶段的,那么任何一个合法的调度都是可串行化的。 既然是定理,那一定是严格成立且可证明的,于是顺藤摸瓜,找到了封锁定理的证明(<事务处理:概念与技术>>这本书的7.5.8.2节)。

  首先我们解析命题:

  条件:良构的事务、两阶段、合法的调度

  结论:是可串行化的。

  在书上找到条件的描述:

  如果事务的每个READ、WRITE、 UNLOCK都被响应的锁覆盖,且所有的锁都是在事务结束时释放,那么称这样的事物是良构的。(mysql的表和行数据在被操作时,都有对应的锁覆盖) 

  如果一个事务可以分成两个阶段,只请求封锁的扩展阶段和只释放锁的收缩阶段,那么称之为两阶段的事务。(mysql采用两阶段封锁协议)

  调度是一组事务的操作的某种合并结果。(mysql支持多事务并行执行)

  一个调度是合法的,如果同一时间没发生两个不同事务的锁冲突。(mysql需要保证并行事务不冲突)

  因为每个事务T都是良构的,所以必定对应着一个解锁操作Unlock,事务T的解锁操作步骤在调度中的索引为St。

  假设在调度中事务T1在事务T2之前执行,T1<<<T2,则事务T2依赖事务T1,使得事务T1对对象O的操作步骤a1在事务T2对对象O的操作步骤a2之前,那么a1和a2必定有一个步骤对象O正覆盖着排他锁(WRITE)(因为如果是两个挨着的读事务(READ)不存在依赖关系,所以他们的执行顺序没有明确的等价执行序列),如果是a1时对象O覆盖着一个XLOCK(排他锁),a2时对象O应该覆盖着一个SLOCK(共享锁)或XLOCK(排他锁),与前面的XLOCK互斥,又由于是两阶段的,所以在a1和a2之间,会存在一个事务T1给对象O解锁的Unlock操作步骤St1,事务T2的解锁操作步骤St2在a2之后,所以有:St1<<<St2,即事务T1的解锁在事务T2的解锁之前。同理在a2是WRITE操作的时候也成立。如果调度是不可串行化的,那么必然存在T1<<<T2时,St2<<<St1,与上述结论矛盾,所以:

  如果一个调度包含的事物都是良构的且为两阶段的,那么该调度是可串行化的。

  可能有人会问,为什么不给每个事务加排他锁来保证多事务执行的串行化呢?

  是因为如果把读锁也定义为排他锁的话,会大大的降低并发读的效率,而查询操作在数据库的操作中占了很大的比例,所以mysql默认采用的可重复读的隔离级别,用两阶段协议和全场景覆盖的锁来保证执行结果的串行化,并没有采用全用排他锁来保证串行化。

  

  

  

mysql的两阶段协议(封锁定理,虫洞事务)的更多相关文章

  1. 使用golang理解mysql的两阶段提交

    使用golang理解mysql的两阶段提交 文章源于一个问题:如果我们现在有两个mysql实例,在我们要尽量简单地完成分布式事务,怎么处理? 场景重现 比如我们现在有两个数据库,mysql3306和m ...

  2. MySQL binlog 组提交与 XA(两阶段提交)

    1. XA-2PC (two phase commit, 两阶段提交 ) XA是由X/Open组织提出的分布式事务的规范(X代表transaction; A代表accordant?).XA规范主要定义 ...

  3. MySQL binlog 组提交与 XA(分布式事务、两阶段提交)【转】

    概念: XA(分布式事务)规范主要定义了(全局)事务管理器(TM: Transaction Manager)和(局部)资源管理器(RM: Resource Manager)之间的接口.XA为了实现分布 ...

  4. MySQL binlog 组提交与 XA(两阶段提交)--1

    参考了网上几篇比较靠谱的文章 http://www.linuxidc.com/Linux/2015-11/124942.htm http://blog.csdn.net/woqutechteam/ar ...

  5. 聊一聊 MySQL 中的数据编辑过程中涉及的两阶段提交

    MySQL 数据库中的两阶段提交,不知道您知道不?这篇文章就简单的聊一聊 MySQL 数据库中的两阶段提交,两阶段提交发生在数据变更期间(更新.删除.新增等),两阶段提交过程中涉及到了 MySQL 数 ...

  6. 全网最牛X的!!! MySQL两阶段提交串讲

    目录 一.吹个牛 二.事务及它的特性 三.简单看下两阶段提交的流程 四.两阶段写日志用意? 五.加餐:sync_binlog = 1 问题 六.如何判断binlog和redolog是否达成了一致 七. ...

  7. flink-----实时项目---day07-----1.Flink的checkpoint原理分析 2. 自定义两阶段提交sink(MySQL) 3 将数据写入Hbase(使用幂等性结合at least Once实现精确一次性语义) 4 ProtoBuf

    1.Flink中exactly once实现原理分析 生产者从kafka拉取数据以及消费者往kafka写数据都需要保证exactly once.目前flink中支持exactly once的sourc ...

  8. MySQL两阶段提交

    参数介绍 innodb_flush_log_at_trx_commit 0: 每隔1s,系统后台线程刷log buffer,也就是把redo日志刷盘,这里会调用fsync,所以可能丢失最后1s的事务. ...

  9. 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究 转载

    1.XA XA是由X/Open组织提出的分布式事务的规范.XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接 ...

随机推荐

  1. ASP.NET Core 3.0 gRPC 拦截器

    目录 ASP.NET Core 3.0 使用gRPC ASP.NET Core 3.0 gRPC 双向流 ASP.NET Core 3.0 gRPC 拦截器 一. 前言 前面两篇文章给大家介绍了使用g ...

  2. tarjan学习(复习)笔记(持续更新)(各类找环模板)

    题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只 ...

  3. go语言教程之浅谈数组和切片的异同

    Hello ,各位小伙伴大家好,我是小栈君,上次分享我们讲到了Go语言关于项目工程结构的管理,本期的分享我们来讲解一下关于go语言的数组和切片的概念.用法和区别. 在go语言的程序开发过程中,我们避免 ...

  4. PHP RSA签名(公钥、私钥)

    签名算法:    Setp.1 确定待签名参数        在请求参数列表中,除去sign参数外,其他需要使用到的参数皆是要签名的参数. 在通知返回参数列表中,除去sign参数外,凡是通知返回回来的 ...

  5. 浅谈oracle中for update 和 for update nowait 和 for update wait x的区别

    在执行update的时候,不加nowait/wait x的时候,当数据记录被锁住的时候,会一直处于等待状态,直到资源锁定被释放: 而加了nowait的时候,马上就会进行反馈“ORA-00054错误,内 ...

  6. deepin MySQL 安装以及编码格式的修改utf-8

    deepin MySQL 安装以及编码格式的修改utf-8: 1.sudo apt-get install mysql-server mysql-client 2.sudo mysql -u root ...

  7. pat 1002 A+B for Polynomials (25 分)

    1002 A+B for Polynomials (25 分) This time, you are supposed to find A+B where A and B are two polyno ...

  8. Mybatis 关联对象不能输出的解决办法

    Mybatis 关联对象不能输出的解决办法 1.如图所示,现在进行查询的时候并没有得到来自另一张表address项 2.我们进行如下配置: (1).在mybatis-config.xml 文件中配置, ...

  9. Cesium小插件改造--clock和timeline

    一.Clock 废话不多说,先上效果图再说.如效果图所示:clock的日期显示为YY/MM/DD这种简洁明了格式,时间则为当前系统时间(也就是北京时间).Clock内部以儒略日(JulianDate) ...

  10. 7. SOFAJRaft源码分析—如何实现一个轻量级的对象池?

    前言 我在看SOFAJRaft的源码的时候看到了使用了对象池的技术,看了一下感觉要吃透的话还是要新开一篇文章来讲,内容也比较充实,大家也可以学到之后运用到实际的项目中去. 这里我使用Recyclabl ...