分布式系统 Distributed Systems 第 13 讲 事务和并发控制 Lecture 13 TRANSACTIONS AND CONCURRENCY CONTROL 王晓阳、张 奇 复旦大学 计算机科学技术学院.

Slides:



Advertisements
Similar presentations
如何學好數學? 黃駿耀老師
Advertisements

辅助核算 3.5.
10 郑和远航.
三个偶像的故事和功绩 ——第12课 明清时期的反侵略斗争 董飞燕.
捣蛋鬼历险记 初一四班 孙嘉佑小组.
中國歷史 明代之患禍及民變.
10 郑和远航 郑和 郑和,1371年生于云南昆阳州(今昆明晋宁县)一个信奉伊斯兰教的回族家庭,原名马和,小字三宝,十一岁时在明太祖朱元璋发动的统一云南的战争中被俘进宫,后当朱元璋四子燕王朱棣的近侍。1403年朱棣登基,史称明成祖。次年正月初一,朱棣念他有勇有谋,屡立奇功,便赐姓“郑”,改称郑和,并提拔为内宫太监,于永乐三年(1405年7月11日)率领庞大船队首次出使西洋。自1405年到1433年,漫长的28年间,郑和船队历经亚非三十余国,涉十万余里,与各国建立了政治,经济,文化的联系,完成了七下西洋的伟
明清 抗击外国侵略的英勇斗争 雅克萨反击战(俄) 戚继光抗倭(日) 郑成功收复台湾(荷兰) 荷兰 俄 罗 斯 日 本 台湾 沙 俄 入 侵
戚继光抗倭.
刑事訴訟法 授課人:林俊益副教授 時間:95.9.~96.6..
妩媚人生 云 计 算 与 大规模数据并行处理技术 黄 宜 华 南 京 大 学 计算机科学与技术系 软件新技术国家重点实验室 妩媚人生 妩媚人生
第16 课 中外的交往与冲突 授课人:鲍婷.
历史上的中日关系.
云南外事外语职业学院 入党积极分子培训 赵田甜.
第四章 清代臺灣的社會文化變遷 第一節 移墾社會的形成
認識食品中毒 一、什麼是食品中毒? 二人或二人以上攝取相同的食品而發生相似的症狀,並且自可疑的食餘檢體及患者糞便、嘔吐物、血液等人體檢體,或者其它有關環境檢體(如空氣、水、土壤等)中分離出相同類型(如血清型、噬菌 體型)的致病原因,則稱為一件“食品中毒”。 但如因攝食肉毒桿菌毒素或急性化學性中毒而引起死亡,即使只有一人,也視為一件“食品中毒”。
題目:四大古文明 班級:六年八 班 組員:賴宣光.游家齊.陳羿文 吳佳芬.許淑婷.許芳瑜..
食 物 中 毒.
琦君 《髻》 S 康倩瑜.
眼乾乾唔使慌.
滑膜皱襞综合征.
“公平”是最热的关键词 1、胡锦涛首次进行“总动员”,提出“在促进发展的同时,把维护社会公平放到更加突出的位置” 。
贵州省公务员面试 备考指导 中公教育 面试讲师 刘运龙.
外 套 各式領型與變化 武 玫 莉 製 作.
第4节 人体对食物的消化吸收.
陈冤之魅,心鬼之泪 ——雾里探花 《东方快车谋杀案》 By第二小组.
高考作文等级评分标准/发展等级10分 深刻 丰富 有文采 有创意 ①透过现象 深入本质 ②揭示问题 产生的原因 ③观点具有 启发作用
文明礼仪在我心 文明礼仪在我心.
第10课 社会生活的变迁.
故事会 盘古开天劈地 在很久很久以前,天地可不象我们现在看到的这样————天高高的在上面,地在我们的脚下,中间隔着几千几万米远。那个时候的天地就象是一个包在大黑壳里的鸡蛋,混混沌沌的,什么也看不清。人们走路都得弯着腰,耕田打猎都很不方便,因为一不小心抬个头,就会碰到天,惹它生气,接着就会招来狂风暴雨。因此所有的植物也都长不高,所以结的粮食和果实都很少,根本就不够大家吃。还经常会发生饿死人的事情。
面向三农,拓宽信息渠道 辐射千村,服务百万农民
三招 让孩子爱上阅读 主讲人:芝莺妈妈 2012年10月19日.
FUZHUANGZHITUYANGBANZHIZUO
如何挑選吳郭魚 嗨~ 餐旅二乙 4a2m0105 白妤潔 4a2m0122 何姿瑩.
学校春季呼吸道传染病预防知识 连云港市疾病预防控制中心
服裝整理概論.
印染纺织类艺术.
创业计划书的编写.
创业计划书撰写.
第九章 进行充分调研 选择自主创业.
香溢饺子馆创业计划书.
第三章 中国的民族民俗 第一节 概论 第二节 汉族 第三节 满族 蒙古族 维吾尔族 回族 朝鲜族 第四节 壮族 土家族 苗族 黎族
第 4 章 投资银行: 基于资本市场的主业架构.
创业数字图书馆.
中国管理科学发展探索 成思危 2006年8月18日于上海复旦大学.
“四文”交融,虚实并举,打造具有鲜明职教特色的校园文化 ——江苏省扬州商务高等职业学校校园文化建设汇报
103年度高職優質化輔助方案計畫申辦及輔導訪視說明會
“十二五”科技发展思路 与科技计划管理 科技部发展计划司 刘敏 2012年9月.
社区妇幼保健工作 江东区妇幼保健院 胡波瑛.
人生不要太圓滿 ◎ 張忠謀.
导致羊水过少的五大因素.
胎教.
怎样进行一次宣讲 何惠玲.
第三课 中国共产党的历程.
[聚會時,請將傳呼機和手提電話關掉,多謝合作]
规范母婴保健服务 努力降低孕产妇死亡率 市卫生局基妇科 朱静.
中国地质科学院矿产资源研究所 财务报账培训
白天的月亮 想與日爭輝 人生不要太圓滿 文字取自於:張忠謀 攝於陽明山 阿道的攝影工作坊.
第十章(上) 实现中华民族的伟大复兴.
营养要均衡.
ㄩ.
高中新课程历史必修(Ⅰ) 教材比较研究 四川师范大学历史文化学院教授 陈 辉 教育部2009普通高中历史课改远程研修资料.
十年职业生涯规划 —— 年 姓名:刘娟 学号:.
主考官眼中的面试 ——面试主考官教你备战2016年国考面试 主讲老师:李海鹏.
国内知名高校 医学院(部、中心) 院系及附属医院设置情况 调研报告
財務報表分析 授課教師:陳依婷.
第六章 可供出售金融资产 一、可供出售金融资产的概念和特征 二、可供出售金融资产的核算.
主讲人:刘文波 (四会国税 政策法规股) 2014年4月
智慧宁波 智慧财税 . 宁波市地方税务局.
第六模块礼仪文书写作 第一节求职信、应聘信 QIUZHIXINYINGPINXIN.
Presentation transcript:

分布式系统 Distributed Systems 第 13 讲 事务和并发控制 Lecture 13 TRANSACTIONS AND CONCURRENCY CONTROL 王晓阳、张 奇 复旦大学 计算机科学技术学院

目录 13.1 简介 13.2 事务 13.3 嵌套事务 13.4 锁 13.5 乐观并发控制 13.6 时间戳排序 13.1 简介 13.2 事务 13.3 嵌套事务 13.4 锁 13.5 乐观并发控制 13.6 时间戳排序 13.7 并发控制方法的比较 13.8 小结

13.1 简介 事务的目标 并发控制 增强可靠性 可恢复对象 利用持久存储保存状态信息 13.1 简介 事务的目标 在多个事务访问对象以及服务器面临故障的情况下,保证 所有由服务器管理的对象始终保持一个一致的状态。 并发控制 增强可靠性 可恢复对象 利用持久存储保存状态信息 事务是由客户定义的针对服务器对象的一组操作,它们组成一个不 可分割的单元,由服务器执行。

13.1 简介 银行事务事例 deposit(amount) //向帐户存amount数量的钱 13.1 简介 银行事务事例 deposit(amount) //向帐户存amount数量的钱 withdraw(amount) //从帐户中取amount数量的钱 getBalance() -> amount //返回帐户中余额 setBalance(amount) //将帐户余额设置成amount Branch接口中的操作 create(name) -> account      //用给定的用户名创建一个新帐户 lookUp(name) -> account     //根据给定的用户名查找帐户,并返回该帐户的一个引用 branchTotal() -> amount  //返回支行中所有帐户余额的总和

13.1 简介 简单的同步机制(无事务) 服务器上的原子操作 - 使用多线程可提高服务器的性能 - 采用锁机制保证线程同步 13.1 简介 简单的同步机制(无事务) 服务器上的原子操作   - 使用多线程可提高服务器的性能   - 采用锁机制保证线程同步   - 原子操作:免受其它线程中执行的并发操作干扰的操作 通过服务器操作的同步加强客户的协同 - 互斥   - 生产者-消费者   Java中的wait和notify方法

13.1 简介 事务的故障模型——Lampson模型 对持久性存储的写操作可能发生故障 - 写操作无效或写入错误的值 - 文件存储可能损坏 13.1 简介 事务的故障模型——Lampson模型 对持久性存储的写操作可能发生故障   - 写操作无效或写入错误的值   - 文件存储可能损坏   - 读数据时可根据校验和发现损坏数据 服务器可能偶尔崩溃 - 进程崩溃后,根据持久存储中的信息恢复   - 服务器不会产生随机故障 消息传递可能由任意长时间的延迟 - 消息可丢失、重复或者损坏   - 接收方能够检测受损消息

13.2 事务 事务的概念 银行事务示例 Transaction T: a.withdraw(100); b.deposit(100);  以原子方式执行的一系列操作,即 1. 它们不受其它并发客户操作的干扰  2. 所有操作或者全部成功完成,或者不产生任何影响 银行事务示例 Transaction T: a.withdraw(100); b.deposit(100); c.withdraw(200); b.deposit(200);

13.2 事务 全有或全无:或者完全成功,或者不留下任何效果 隔离性 故障原子性 即使服务器崩溃,事务的效果也是原子的。 持久性  即使服务器崩溃,事务的效果也是原子的。 持久性  一旦事务完成,它的所有效果将被保存到持久存储中 隔离性 每个事务的影响不受其它事务的影响 ACID特性 Atomicity 原子性 Consistency 一致性 Isolation 隔离性 Durability 持久性

13.2 事务 使用一个事务 事务协调者 - 作用 创建和管理事务 - 示例 openTransaction() -> trans;  - 作用   创建和管理事务   - 示例 openTransaction() -> trans; 开始一个新事务,并返回该事务的唯一TID, TID用于事务的其它操作。 closeTransaction(trans) -> (commit, abort); 结束事务:若返回commit,则成功提交;否则返回abort,标示放弃。 abortTransaction(trans); 放弃事务。

13.2 事务 使用一个事务(续) 事务的完成通常需要一个客户程序、若干可恢复对象和一个协调 者之间的合作 事务执行结果 事务执行历史示例 事务的完成通常需要一个客户程序、若干可恢复对象和一个协调 者之间的合作 事务执行结果  - 完全成功  - 放弃事务 客户放弃事务 服务器放弃事务 事务执行历史示例

13.2 事务 成功执行 被客户放弃 被服务器放弃 openTransaction 操作 服务器 放弃事务 向客户报告ERROR closeTransaction abortTransaction

13.2 事务 并发控制(一) 更新丢失问题 初值:帐户A、B、C分别为$100、$200、$300  操作:两次转帐(A → B、C → B),每次转帐金额为B 当前帐户余额的10% 期望结果:B的终值应为$242

13.2 事务 事务T: balance = b.getBalance(); b.setBalance(balance*1.1); a.withdraw(balance/10) 事务U: c.withdraw(balance/10) balance = b.getBalance(); $200 $220 $80 $280

13.2 事务 并发控制(二) 不一致检索 初值:帐户A、B分别为$200、$200 操作:转帐+查询银行所有帐户的总余额  操作:转帐+查询银行所有帐户的总余额 期望结果:总余额为$400

13.2 事务 事务V: a.withdraw(100) b.deposit(100) 事务W: aBranch.branchTotal() $100 total = a.getBalance() total = total+b.getBalance() $300 total = total+c.getBalance()

13.2 事务 并发控制(三) 串行等价性 串行等价的交错执行 使用串行等价性作为并发执行的判断标准,可防止更新丢失 和不一致检索问题。 多事务正确运行效果推断 若每个事务知道它单独执行的正确效果,则可以推断出这些事务按 某种次序一次执行一个事务的效果。 串行等价的交错执行 并发事务交错执行操作的效果等同于按某种次序一次执行一个事务 的效果。 使用串行等价性作为并发执行的判断标准,可防止更新丢失 和不一致检索问题。

13.2 事务 事务T: balance = b.getBalance() b.setBalance(balance*1.1) a.withdraw(balance/10) 事务U: c.withdraw(balance/10) balance = b.getBalance() $200 $220 $242 $80 $278

13.2 事务 事务V: a.withdraw(100); b.deposit(100) 事务W: aBranch.branchTotal() $100 $300 total = a.getBalance() total = total+b.getBalance() $400 total = total+c.getBalance() ...

13.2 事务 并发控制(三) 冲突操作 - 冲突 两个操作的执行效果和它们的执行次序相关 - Read和Write操作的冲突规则  - 冲突   两个操作的执行效果和它们的执行次序相关  - Read和Write操作的冲突规则 不同事务的操作 是否冲突 原因 read 否 由于两个read操作的执行效果不依赖这 两个操作的执行次序 write 是 由于一个read操作和一个write操作的执 行效果依赖于它们的执行次序 由于两个write操作的执行效果依赖于这

13.2 事务 并发控制(三) 冲突操作(续) - 串行等价性 - 非串行等价地执行事务示例  - 串行等价性 两个事务串行等价的充要条件是,两个事务中所有的冲突操作 都按相同的次序在它们访问的对象上执行。  - 非串行等价地执行事务示例   事务T:x=read(i); write(i,10); write(j,20); 事务U:y=read(j); write(j,30); z=read(i);

13.2 事务 事务T: 事务U: x = read(i) write(i, 10) y = read(j) write(j, 30) z = read (i)

13.2 事务 并发控制(四) 并发控制协议 依据 串行等价性 目的 将访问对象的并发事务串行化 方法 锁 乐观并发控制 时间戳排序

13.2 事务 事务放弃时的恢复(一) 脏数据读取 某个事务读取了另一个未提交事务写入的数据 事务T放弃时的脏数据读取 事务T:  某个事务读取了另一个未提交事务写入的数据 事务T: a.getBalance() a.setBalance(balance + 10) 事务U: a.setBalance(balance + 20) balance = a.getBalance() $100 $110 $130 commit transaction abort transaction 事务T放弃时的脏数据读取

13.2 事务 事务放弃时的恢复(二) 事务可恢复性 策略:推迟事务提交,直到它读取更新结果的其它事 务都已提交。 连锁放弃  策略:推迟事务提交,直到它读取更新结果的其它事 务都已提交。 连锁放弃   - 某个事务的放弃可能导致后续更多事务的放弃   - 防止方法:只允许事务读取已提交事务写入的对 象

13.2 事务 事务放弃时的恢复(三) 过早写入 - 一些数据库在放弃事务时,将变量的值恢复到该事务所有 write操作的“前映像”。 a.setBalance(105) 事务U: a.setBalance(110) $100 $105 $110

13.2 事务 事务放弃时的恢复(四) 事务的严格执行 - 严格执行:read和write操作都推迟到写同一对象的其 它事务提交或放弃后进行   - 可以真正保证事务的隔离性 临时版本   - 目的:事务放弃后,能够清除所有对象的更新   - 方法 事务的所有操作更新将值存储在自己的临时版本中 事务提交时,临时版本的数据才会用来更新对象

13.3 嵌套事务 概念 嵌套事务:允许事务由其它事物构成 顶层事务(Top-Level) 子事务(Sub-transaction) 示例

13.3 嵌套事务 T : 顶层事务 T1 = openSubTransaction T2 = openSubTransaction prov.commit prov. commit abort commit T2: T12: T21: T211:

13.3 嵌套事务 优点 提交规则 并发度高 子事务可并发运行 健壮性强 子事务可以独立提交和放弃 事务在它的子事务完成以后,才能提交或放弃   子事务可并发运行 健壮性强   子事务可以独立提交和放弃 提交规则 事务在它的子事务完成以后,才能提交或放弃 子事务完成后,可独立决定是暂时提交或放弃 父事务放弃时,所有的子事务都被放弃 若子事务放弃,则父事务可以决定是否放弃 若顶层事务提交,则所有暂时提交的事务将最终提交 Email 的例子

13.4 锁 互斥锁是一种简单的事务串行化实现机制 事务访问对象前请求加锁 若对象已被其它事务锁住,则请求被挂起,直至对象 被解锁 使用示例

13.4 锁 事务T balance = b.getBalance() b.setBalance(bal*1.1) a.withdraw(bal/10) 事务U c.withdraw(bal/10) 操作 锁 openTransaction bal = b.getBalance() 锁住B 锁住A 等待事务T在B上的锁 closeTransaction 对A,B解锁 锁住C 对B,C解锁 …

13.4 锁 两阶段加锁(two-phrase locking) 严格的两阶段加锁(strict two-phrase locking) 目的:保证两个事务的所有的冲突操作对必须以相同的次 序执行 增长阶段:不断获取新锁 收缩阶段:释放锁 严格的两阶段加锁(strict two-phrase locking) 目的:防止事务放弃导致的脏数据读取、过早写入等问题 方法:所有在事务执行过程中获取的新锁必须在事务提交 或放弃后才能释放 粒度的例子

13.4 锁 读锁和写锁 事务的操作冲突规则 读锁和写锁的兼容性 目的:提高并发度 支持多个并发事务同时读取某个对象 允许一个事务写对象 如果事务T已经对某个对象进行了读操作,那么并发 事务U在事务T提交或放弃前不能写该对象。 如果事务T已经对某个对象进行了写操作,那么并发 事务U在事务T提交或放弃前不能写或读该对象。 读锁和写锁的兼容性

13.4 锁 被请求的锁 对某一对象 read write 已设置的锁 none OK OK read OK wait write 等待

13.4 锁 1. When an operation accesses an object within a transaction: (a) If the object is not already locked, it is locked and the operation proceeds. (b) If the object has a conflicting lock set by another transaction, the transaction must wait until it is unlocked. (c) If the object has a non-conflicting lock set by another transaction, the lock is shared and the operation proceeds. (d) If the object has already been locked in the same transaction, the lock will be promoted if necessary and the operation proceeds. (Where promotion is prevented by a conflicting lock, rule (b) is used.) 2. When a transaction is committed or aborted, the server unlocks all objects it locked for the transaction. Figure 16.16 Use of locks in strict two-phase locking

13.4 锁 锁的实现 锁的授予通常由服务器上一个对象实现—锁管理器 每个锁都是Lock类的一个实例 - 被锁住对象的标示符   - 被锁住对象的标示符   - 当前拥有该锁的事务的标示符   - 锁的类型

13.4 锁 public class Lock { private Object object; // the object being protected by the lock private Vector holders; // the TIDs of current holders private LockType lockType; // the current type public synchronized void acquire(TransID trans, LockType aLockType ){ while(/*another transaction holds the lock in conflicing mode*/) { try { wait(); }catch ( InterruptedException e){/*...*/ } } if(holders.isEmpty()) { // no TIDs hold lock holders.addElement(trans); lockType = aLockType; } else if(/*another transaction holds the lock, share it*/ ) ){ if(/* this transaction not a holder*/) holders.addElement(trans); } else if (/* this transaction is a holder but needs a more exclusive lock*/) lockType.promote();

13.4 锁 public synchronized void release(TransID trans ){ holders.removeElement(trans); // remove this holder // set locktype to none notifyAll(); }

13.4 锁 锁的实现(续) LockManager类   所有的事务要求加锁和解锁的请求都被送往类 LockManager的某个实例。

13.4 锁 public class LockManager { private Hashtable theLocks; public void setLock(Object object, TransID trans, LockType lockType){ Lock foundLock; synchronized(this){ // find the lock associated with object // if there isn’t one, create it and add to the hashtable } foundLock.acquire(trans, lockType); // synchronize this one because we want to remove all entries public synchronized void unLock(TransID trans) { Enumeration e = theLocks.elements(); while(e.hasMoreElements()){ Lock aLock = (Lock)(e.nextElement()); if(/* trans is a holder of this lock*/ ) aLock.release(trans);

13.4 锁 嵌套事务的加锁需求 嵌套事务集 - 要求:不能观察到其它嵌套事务集的部分效果   - 要求:不能观察到其它嵌套事务集的部分效果   - 实现方法:父事务继承子事务的所有锁,锁的继承从 底层向高层传递。 嵌套事务集中的事务 - 要求:不能观察到同一事务集中其它事务的部分效果   - 实现方法:父事务不允许和子事务并发运行;同层次 的事务可并发执行。

13.4 锁 嵌套事务的加锁规则(一) 获得读锁   如果子事务获取了某个对象的读锁,那么其它活动 事务不能获取该对象的写锁,只有该子事务的父事务 们可以持有该写锁。 获得写锁    如果子事务获取了某个对象的写锁,那么其它活 动事务不能获取该对象的写锁或读锁,只有该子事务 的父事务们可以持有该写锁或读锁。

13.4 锁 嵌套事务的加锁规则(二) 提交 子事务提交时,它的所有锁由父事务继承,即允许 父事务保留与子事务相同模式的锁。 放弃   子事务提交时,它的所有锁由父事务继承,即允许 父事务保留与子事务相同模式的锁。 放弃   子事务放弃时,它的所有锁都被丢弃。如果父事务 已经保留了这些锁,那么它可以继续保持这些锁。

13.4 锁 死锁(一) 死锁场景示例 两个事务都在等待并且只有对方释放锁后才能继续执行 事务T 事务U 操作 锁  两个事务都在等待并且只有对方释放锁后才能继续执行 事务T 事务U 操作 锁 a.deposit(100); 给A加锁 b.deposit(200) 给B加写锁 b.withdraw(100) 等待事务U a.withdraw(200); 等待事务T 在B上的锁 在A上的锁

13.4 锁 死锁(二) 定义 死锁是一种状态,在该状态下一组事务中的每一个事 务都在等待其它事务释放某个锁。  死锁是一种状态,在该状态下一组事务中的每一个事 务都在等待其它事务释放某个锁。 等待图(wait-for graph)  表示事务之间的等待关系。 B A 等待 持有 T U

13.4 锁 死锁(三) 复杂等待图示例 - 事务T、U和V共享对象C上的读锁 - 事务W拥有对象B上的写锁   - 事务T、W请求对象C上的写锁   - V对象C上的写锁 C T U V 持有 W B 等待

13.4 锁 预防死锁 更新锁 每个事务在开始运行时锁住它要访问的所有对象 - 一个简单的原子操作 - 不必要的资源访问限制   - 一个简单的原子操作   - 不必要的资源访问限制   - 无法预计将要访问的对象 预定次序加锁   - 过早加锁 - 减少并发度 更新锁 避免死锁 在数据项上加更新锁的事务可以读该数据项,但该锁与加在同一 数据项上的更新相冲突。

13.4 锁 死锁检测 锁超时:解除死锁最常用的方法之一 使用超时解除死锁示例 维护等待图 检测等待图中是否存在环路 若存在环路,则选择放弃一个事务 锁超时:解除死锁最常用的方法之一 每个锁都有一个时间期限 超过时间期限的锁成为可剥夺锁 若存在等待可剥夺锁保护的对象,则对象解锁 使用超时解除死锁示例

13.4 锁 事务 T 事务 U 操作 锁 a.deposit(100); 给A加写锁 b.deposit(200) 给B加写锁 b.withdraw(100) 等待事务U在 a.withdraw(200); 等待事务T 在A上的锁 B上的锁(超时) T在A上的锁 变成可剥夺的, 释放A上的锁, 放弃T 释放A,B上的锁

13.4 锁 在加锁机制中增加并发度 双版本加锁 层次锁 读/写操作 - 写操作对象可为临时版本 - 读操作对象为提交版本   - 写操作对象可为临时版本   - 读操作对象为提交版本 读锁、写锁和提交锁 - 读锁:在读操作前为对象设置读锁   - 读锁:在写操作前为对象设置写锁   - 提交锁:收到提交事务请求后,将写锁转换为提交锁  锁的相容性

13.4 锁 双版本加锁(续) 锁的相容性 对某个对象 要设置的锁 read write commit 已设置的锁 none OK 等待

13.4 锁 层次锁 混合粒度的层次锁 每个事务按需要锁住部分数据 锁的拥有者能显式访问该节点并隐式访问它的子节点 每个事务按需要锁住部分数据  锁的拥有者能显式访问该节点并隐式访问它的子节点 给子节点加锁时,需要在父节点和祖先节点设置试图 锁 在每一层,设置父锁与设置等价的子辈锁具有相同的 效果 锁的相容性 银行例子

13.4 锁 对某个对象 要设置的锁 read write I-read I-write 已设置的锁 none OK 等待

13.4 锁 层次锁示例 星期二 星期三 星期四 星期五 星期 星期一 9:00–10:00 时间段 10:00–11:00 11:00–12:00 12:00–13:00 13:00–14:00 14:00–15:00 15:00–16:00

13.5 乐观并发控制 锁机制的缺点 乐观策略 维护开销大 会引起死锁 并发度低 基于事实:在大多数应用中,两个客户事务访问同一个对 象的可能性很低。 方法 - 访问对象时不作检查操作   - 事务提交时检测冲突   - 若存在冲突,则放弃一些事务

13.5 乐观并发控制 事务的三个阶段 工作阶段 - 每个事务拥有所修改对象的临时版本 - 每个事务维护访问对象的两个集合:读集合和写集合  - 每个事务拥有所修改对象的临时版本 - 每个事务维护访问对象的两个集合:读集合和写集合 验证阶段 - 在收到closeTransaction请求,判断是否与其它事务存 在冲突。 更新阶段 - 提交通过验证的事务

13.5 乐观并发控制 事务的验证 事务号 - 每个事务在进入验证阶段前被赋予一个事务号 - 事务号是整数,并按升序分配  - 每个事务在进入验证阶段前被赋予一个事务号 - 事务号是整数,并按升序分配  - 事务按事务号顺序进入验证阶段 - 事务按事务号提交 冲突规则  - 事务Tv的验证测试  - Ti和Tv之间的存在冲突

13.5 乐观并发控制 事务Tv对事务Ti而言是可串行化的: Tv Ti 规则 write read 1. Ti不能读取Tv写的对象

13.5 乐观并发控制 向后验证 检查它的读集是否和其它较早重叠事务的写集是否重叠 算法  - startTn: Tv进入工作阶段时已分配的最大事务号码  - finishTn: Tv进入验证阶段时已分配的最大事务号码 验证失败后,冲突解决方法   放弃当前进行验证的事务 Boolean valid = true For ( int Ti = startTn +1; Ti <= finishTn; Ti ++) { if (read set of Tv intersects write set of Ti) valid = false }

13.5 乐观并发控制 向后验证(续) 事物的验证过程 - T1、 T2、T3是较早开始的事务 - T1在Tv开始之前提交 - startTn+1=T2,finishTn=T3

13.5 乐观并发控制 向后验证过程必须比较Tv的读集和T2、T3的写集 较早提交的事务 工作阶段 验证阶段 更新阶段 T v 正在验证的事务 2 3 以后的活动事务 active 向后验证过程必须比较Tv的读集和T2、T3的写集

13.5 乐观并发控制 向前验证 比较Tv的写集合和所有重叠的活动事务的读集合 算法  - 设活动事务具有连续的事务标示符active1~activeN 验证失败后,冲突解决方法   - 放弃当前进行验证事务 - 推迟验证   - 放弃所有冲突的活动事务,提交已验证事务 Boolean valid = true for ( int Tid = active1 +1; Tid <= activen; Tid ++){ if (write set of Tv intersects read set of Tid) valid = false }

13.5 乐观并发控制 向前验证(续) 事物的验证过程   - active1、 active2是较Tv晚开始的事务

13.5 乐观并发控制 向前验证过程必须比较Tv的写集和active1、active2的读集 较早提交的事务 工作阶段 验证阶段 更新阶段 正在验证的事务 2 3 以后的活动事务 active 向前验证过程必须比较Tv的写集和active1、active2的读集

13.5 乐观并发控制 向前验证和向后验证的比较 饥饿 向前验证在处理冲突时比较灵活 向后验证将较大的读集合和较早事务的写集合进行比较 向前验证将较小的写集合和活动事务的读集合进行比较 向后验证需要存储已提交事务的写集合 向前验证不得不允许在验证过程中开始新事务 饥饿 由于冲突,某个事务被反复放弃,阻止它最终提交的现象。 利用信号量,实现资源的互斥访问,避免事务饥饿

13.6 时间戳排序 基本思想 时间戳 - 每个事务在启动时被赋予一个唯一的时间戳 - 时间戳定义了该事务在事务时间序列中的位置   - 每个事务在启动时被赋予一个唯一的时间戳 - 时间戳定义了该事务在事务时间序列中的位置   - 不会引起死锁 冲突规则   -写请求有效:对象的最后一次读访问或写访问由一个较 早的事务执行 -读请求有效:对象的最后一次写访问由一个较早的事物 执行

13.6 时间戳排序 基于时间戳的并发控制 临时版本 - 写操作记录在对象的临时版本中 - 临时版本中的写操作对其它事务不可见   - 写操作记录在对象的临时版本中   - 临时版本中的写操作对其它事务不可见 写时间戳和读时间戳   - 已提交对象的写时间戳比所有临时版本都要早 - 读时间戳集用集合中的最大值来代表 - 事务的读操作作用于时间戳小于该事务时间戳的最 大写时间戳的对象版本上

13.6 时间戳排序 基于时间戳的并发控制(续) 操作冲突 规则 Tc Ti 1. write read 如果Ti>Tc,那么Tc不能写被Ti读过的对象, 这要求Tc≥该对象的最大读时间戳 2. 3. 如果Ti>Tc,那么Tc不能写被Ti写过的对象, 这要求Tc≥已提交对象的写时间戳 如果Ti>Tc,那么Tc不能读被Ti写过的对象,

13.6 时间戳排序 时间戳排序的写规则 是否接受事务Tc对对象D执行的写操作 示例 if (Tc ≥ D的最大读时间戳 && Tc > D的提交版本上的写时间戳) 在D的临时版本上执行写操作,写时间戳置为 Tc else /* 写操作太晚了 */ 放弃事务 Tc

13.6 时间戳排序 a) T3写操作 b) T3写操作 时事务Ti产生的对象 (写时间戳为Ti) T1<T2<T3<T4 之前 2 之前 T T 图例 1 2 T i 提交版本 之后 T T 2 3 之后 T T T 1 2 3 T i 时间 时间 a) T3写操作 b) T3写操作 临时版本 时事务Ti产生的对象 (写时间戳为Ti) T1<T2<T3<T4 Transaction T T T aborts 之前 1 4 之前 4 之后 T T T 之后 T 1 3 4 4 时间 时间 c) T3写操作 d) T3写操作

13.6 时间戳排序 时间戳排序的读规则 是否接受事务Tc对对象D执行的读操作 示例 if (Tc ≥ D提交版本的写时间戳) 设Dselected是D的具有最大写时间戳的版本≤Tc; if (Dselected已提交) 在Dselected版本上完成读操作 else 等待直到形成版本的事务提交或放弃,然后重新应用读规则; }else 放弃事务 Tc

13.6 时间戳排序 事务中止 T 时间 读操作执行 T 被选中 时间 (b) T3 读操作 (a) T3 读操作 (c) T3 读操作 图例: T T T 2 2 4 T i 被选中 被选中 时间 时间 (b) T3 读操作 提交版本 (a) T3 读操作 T i 事务中止 读操作等待 临时版本 T T T 1 2 4 时事务Ti产生的对象 (写时间戳为Ti) T1<T2<T3<T4 被选中 时间 时间 (c) T3 读操作 (d) T3 读操作

13.6 时间戳排序 对象的不同版本及其时间戳 T U A B C RTS WTS RTS WTS RTS WTS {} S {} S {} openTransaction bal = b.getBalance() {T} openTransaction b.setBalance(bal*1.1) S, T bal = b.getBalance() wait for T S, T a.withdraw(bal/10) commit T T bal = b.getBalance() {U} b.setBalance(bal*1.1) T, U c.withdraw(bal/10) S, U

13.6 时间戳排序 多版本时间戳排序 基本思想 - 每个对象维护一个已提交版本列表 - 过迟到达的读操作从提交版本中获取信息 冲突规则   - 每个对象维护一个已提交版本列表   - 过迟到达的读操作从提交版本中获取信息 冲突规则   - Tc不能写事务Ti读过的对象,其中Ti>Tc 写规则 示例 if (DmaxEarlier 的读时间戳≤Tc ) 在 D的临时版本上完成写操作,并标记上写时间戳 Tc else 放弃事务Tc

13.6 时间戳排序 时间 T 4 write; 5 read; 3 2 1 < T 图例: 临时版本 提交版本 i k 事务 Ti产生的对象 (写时间戳为Ti 且读时间戳为Tk)

13.7 并发控制方法的比较 时间戳排序 两阶段加锁 时间戳排序和两阶段加锁均属采用悲观方法 静态地决定事务之间的串行顺序 对读操作占优的事务而言,优于两阶段加锁机制 冲突规则 两阶段加锁 动态决定事务之间的串行顺序 对更新操作占优的事务而言,优于时间戳排序 时间戳排序和两阶段加锁均属采用悲观方法

13.7 并发控制方法的比较 乐观方法 并发事务之间的冲突较少时,性能较高 放弃事务时,需要重复大量工作 悲观方法 简单 并发度低

13.8 小结 事务 嵌套事务 并发控制 子事务可并发执行 子事务可独立提交和放弃 准则:串行等价性 两个问题:更新丢失和不一致检索 事务放弃时的恢复

13.8 小结 并发控制方法 两阶段加锁 时间戳排序 乐观方法

Question?