事务并发调度的可串行性及两段锁协议
一、并发调度
并发调度啥意思?
就是当很多事务同时执行的时候应该按照什么顺序执行,应该按照排队的顺序执行,这就是 串行调度 。
串行执行肯定是正确的,但是改变一下位置有影响吗?
这就要看改变顺序之后执行的结果是否和不改变顺序执行的结果一致了。
如果改变顺序之后执行的结果和串行调度的执行结果一致,那么就说这种调度是 可串行化调度。
可串行性是并发事务正确调度的准则。
比如:
事务 T1: 读 B A=B+1;写回 A;
事务 T2: 读 A B=A+1;写回 B;
假设 A、B 的初始值都是 2,串行调度指的就是先执行 T1 再执行 T2,或者先执行 T2 再执行 T1,这是没有区别的,都是正确的。
1、先执行 T1:结果是 A=3,B=4;
2、先执行 T2:结果是 B=3,A=4;
其实这里执行的顺序可以是(R
代表读,W
代表写),这两个都是 串行调度 :
1、R1(B) W1(A) R2(A) W2(B)
2、R2(A) W2(B) R1(B) W1(A)
我们只需要保证对同一数据对象的 读写(写读)操作
和 写写操作
的相对位置不变即可。
涉及对同一数据对象的读写操作称为 冲突操作 。
解释一下前面的意思,这里的同一数据对象假设是 A ,W1(A) R2(A)
就是对同一数据对象
的读写操作,那么他们的顺序是不能调换的,不然数据的结果就会改变。这里的顺序是先 写A
再读 A
,相对位置指的是他们中间可以有其他的操作。
比如,在上一个例子中,如果执行的顺序改成下面的样子:
R1(B) R2(A) W1(A) W2(B)
这就不对了,因为改变了关于数据对象 A
的读写顺序,应该是先写再读,因为这两个是冲突操作,所以不能随便调换位置,现在调换了无论如何也不能通过 交换不冲突操作的位置
变成那两个串行调度中的任何一个了。
总之:不管是同一个事务还是多个事务操作,只要是涉及对同一数据对象的
读写操作
或写写操作
调换顺序的时候就要谨慎一点,不要改变了原来的结果。
除了冲突操作之外的操作称为不冲突操作,如果一个调度通过 交换不冲突操作 的次序得到的另一个调度是串行的,那么称这个调度为 冲突可串行化 的调度。
冲突可串行化调度只是可串行化调度的一种。有的时候就算改变了位置结果也不变。
二、两段锁协议
两段锁协议是为了保证事务并发调度的正确性,简称 2PL
协议。
- 第一阶段是获得锁:
扩展阶段
:只允许加锁; - 第二阶段是释放封锁:
收缩阶段
:只允许解锁;
如果并发执行的所有事务都遵循两段锁协议,那么对这些事务的任何并发调度都是可串行化的。
可能大家回想到预防死锁时使用的 一次封锁法 。他们的区别在于两段锁协议只是说加锁的时候在一个阶段完成,没说要用的所有数据都必须加锁,而后者则要求所有使用到的数据必须加锁而且是在刚开始的加锁时期;所以只要是使用一次封锁法的协议都遵循两段锁协议,同时也说明两段锁协议也有死锁问题。
关于死锁这里提一嘴,有两种方法解决:
- 一是预防:一次封锁法、顺序封锁法;
- 二是解决:超时法、等待图法。
其中等待图法指的是有一个 有向图
,每个 节点
表示正在执行的事务,每个 边
表示事务等待的情况,如果图中存在环路则说明出现了死锁。一般是选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有的锁,使其他事务继续运行下去。
另外对于封锁对象的大小不同,比如封锁一个元组,一张表或者整个数据库,分为不同的封锁粒度;这个时候就要分粒度封锁,在分粒度封锁的基础之上又发明了一种方法叫做意向锁
。
那么这个意向锁又是个什么东西呢?
意向锁建立在一个多粒度树
上面,多粒度树就是将整个数据库按照对象的大小建立一棵树;
这个时候你在一个节点上面加上一个意向锁,那么它以及他的子节点默认被加锁;
具有意向锁的多粒度封锁方法提高了系统的并发度,减少了加锁和解锁的开销。
- 左手用R右手Python系列——使用多进程进行任务处理
- 2017.9.17校内noip模拟赛解题报告
- MySQL基础入门——MySQL与R语言、Python交互
- BizTalk Orchestration execute Flat file disassembler ReceivePipeline
- MySQL基础入门系列之——字符与日期数据处理
- P2038 无线网络发射器选址
- ggplot2双坐标轴的解决方案
- Modifying namespace in XML document programmatically
- ggplot2学习笔记——图例系统及其调整函数
- 一款脑洞大开的表格可视化神器
- P3908 异或之和
- P1939 【模板】矩阵加速(数列)
- R语言学习笔记之——数据处理神器data.table
- P3389 【模板】高斯消元法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 马上2021年了线性表你还不知道原理?给老王整的明明白白
- 分治-芯片测试问题
- 你说啥什么?注解你还不会?
- Mybatis系列第五讲 Mapper接口多种方式传参详解、原理、源码解析
- Mybatis系列第十讲 动态SQL,这么多种你都会?
- 3D图形学线代基础
- Splash抓取jd
- codeforces 1395C(暴力枚举)
- 不到100行代码搞定Python做OCR识别身份证,文字等各种字体
- codeforces 1389B(贪心)
- 又一个自动生成项目目录组件tree-cli,快速生成Readme项目结构
- 用Vue CLI创建uni-app,摆脱HBuilder,npm命令行运行及发布
- codeforces 1133D(map+精度控制)
- 1024程序员节 | 我在腾讯自研数据库,我为技术代言
- jasmine spyOn的单步调试