mysql的两阶段协议(封锁定理,虫洞事务)
我们都知道数据库的事务具有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的两阶段协议(封锁定理,虫洞事务)的更多相关文章
- 使用golang理解mysql的两阶段提交
使用golang理解mysql的两阶段提交 文章源于一个问题:如果我们现在有两个mysql实例,在我们要尽量简单地完成分布式事务,怎么处理? 场景重现 比如我们现在有两个数据库,mysql3306和m ...
- MySQL binlog 组提交与 XA(两阶段提交)
1. XA-2PC (two phase commit, 两阶段提交 ) XA是由X/Open组织提出的分布式事务的规范(X代表transaction; A代表accordant?).XA规范主要定义 ...
- MySQL binlog 组提交与 XA(分布式事务、两阶段提交)【转】
概念: XA(分布式事务)规范主要定义了(全局)事务管理器(TM: Transaction Manager)和(局部)资源管理器(RM: Resource Manager)之间的接口.XA为了实现分布 ...
- MySQL binlog 组提交与 XA(两阶段提交)--1
参考了网上几篇比较靠谱的文章 http://www.linuxidc.com/Linux/2015-11/124942.htm http://blog.csdn.net/woqutechteam/ar ...
- 聊一聊 MySQL 中的数据编辑过程中涉及的两阶段提交
MySQL 数据库中的两阶段提交,不知道您知道不?这篇文章就简单的聊一聊 MySQL 数据库中的两阶段提交,两阶段提交发生在数据变更期间(更新.删除.新增等),两阶段提交过程中涉及到了 MySQL 数 ...
- 全网最牛X的!!! MySQL两阶段提交串讲
目录 一.吹个牛 二.事务及它的特性 三.简单看下两阶段提交的流程 四.两阶段写日志用意? 五.加餐:sync_binlog = 1 问题 六.如何判断binlog和redolog是否达成了一致 七. ...
- 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 ...
- MySQL两阶段提交
参数介绍 innodb_flush_log_at_trx_commit 0: 每隔1s,系统后台线程刷log buffer,也就是把redo日志刷盘,这里会调用fsync,所以可能丢失最后1s的事务. ...
- 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究 转载
1.XA XA是由X/Open组织提出的分布式事务的规范.XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接 ...
随机推荐
- 从V神到以太坊——以太坊发展简史
以太坊的出现,让人们的认识从比特币飞跃到了区块链本身.使得区块链技术在非金融领域的普遍应用成为可能,同时,也被认为是区块链2.0时代的标志,是区块链技术发展史上重要的里程碑. 以太坊的故事,要从比特币 ...
- mysql cpu使用率过高解决方法
mysql cpu使用率过高解决方法 1 mysql查看正在运行的语句 并且查看运行最多的mysql语句 MySQL 打开 general log 后,所有的查询语句都会记录在 general log ...
- .NET Core 对龙芯的支持情况和对 .NET Core 开发嵌入式的思考
目录 .NET Core 对龙芯的支持情况和对 .NET Core 开发嵌入式的思考 一,遗憾的尝试 二,.NET Core在嵌入式下的几点不足 三,.NET Core 龙芯移植的进展和资料 .NET ...
- C语言程序设计100例之(8):尼科彻斯定理
例8 尼科彻斯定理 题目描述 尼科彻斯定理可以叙述为:任何一个整数的立方都可以表示成一串连续的奇数的和.需要注意的是,这些奇数一定是连续的,如:1,3,5,7,9,…. 例如,对于整数5,5*5 ...
- 关于GDAL读写Shp乱码的问题总结
目录 1. 正文 1.1. shp文件本身的编码的问题 1.2. 设置读取的编码方式 1.2.1. GDAL设置 1.2.2. 解码方式 1.2.3. 其他 2. 参考 1. 正文 最近在使用GDAL ...
- linux中dd相关命令骚操作
一.dd如何快速将磁盘写满 方法一: dd if=/dev/zero of=/tmp/file bs=1G count=10 # 参数解释 1. if=文件名:输入文件名,缺省为标准输入.即指定源文件 ...
- PHP Laravel5实现的RBAC权限管理操作示例
根据不同的权限,在菜单栏显示不同的功能,只对菜单进行了限制,若对路由也进行限制,可以根据菜单的例子,请自行完善,开发.下面请认真学习一下laravel的RBAC设计 1.建表(用户表.角色表.权限表. ...
- Spring Bean的定义及作用域
目录: 了解Spring的基本概念 Spring简单的示例 Bean的定义 简单地说Bean是被Spring容器管理的Java对象,Spring容器会自动完成对Bean的实例化. 那么什么是容器呢?如 ...
- PHP的两种选择防止sql注入
1.使用PDO: $stmt = $pdo->prepare('SELECT * FROM user WHERE name = :name'); $stmt->execute(array( ...
- Unix, Linux以及NT内核和它们各自衍生的系统关系图