文档详情

第09章 事务管理与并发控制.ppt

发布:2017-05-30约9.66千字共90页下载文档
文本预览下载声明
避免死锁 相同顺序法 所有的用户程序约定都按相同的顺序来封锁表 一次封锁法 为了完成一个事务,一次性封锁所需要的全部表 两阶段封锁协议 所有事务都必须将对数据的封锁分为封锁和释放两个阶段 避免死锁的封锁 两阶段封锁协议 第一阶段称为扩展阶段,这一阶段获得各种类型的封锁,但是不能释放任何封锁。 第二阶段称为收缩阶段,这一阶段释放各种类型的封锁,一旦开始释放封锁,则不能再申请任何类型的封锁。 注意,两阶段封锁协议和一次封锁法的异同之处。一次封锁法遵守两阶段封锁协议;但是两阶段封锁协议并不要求一次封锁所有需要封锁的数据。两阶段封锁协议仍有可能发生死锁。 举例: 遵守两阶段锁协议 LOCK A … LOCK B … LOCK C … UNLOCK B … UNLOCK A … UNLOCK C 没遵守两阶段锁协议 LOCK A … UNLOCK A… LOCK B … LOCK C … UNLOCK C … UNLOCK B 发现死锁 超时法 即一个事务在等待的时间超过了规定的时限后就认为发生了死锁。 这种方法非常不可靠,如果设置的等待时限长,则不能及时发现死锁;如果设置的等待时限短,则可能会将没有发生死锁的事务误判为死锁。 发现死锁 等待图法 即通过有向图判定事务是否是可串行化的,如果是则说明没有发生死锁,否则说明发生了死锁。 具体思路是:用节点来表示正在运行的事务,用有向边来表示事务之间的等待关系,如右图所示,如果有向图中发现回路,则说明发生了死锁。 解决死锁 发现死锁后解决死锁的一般策略是:自动使“年轻”的事务(即完成工作量少的事务)先退回去,然后让“年老”的事务(即完成工作量多的事务)先执行,等“年老”的事务完成并释放封锁后,“年轻”的事务再重新执行。 “活锁” 没有发生死锁也有可能某个事务永远处于等待状态 “活锁” T1:事务A共享封锁资源S,成功 T2:事务B试图独占封锁资源S,等待 T3:事务C在A释放封锁S之前,共享封锁S成功 T4:事务D在C释放封锁S之前,共享封锁S成功 …… 结果事务B无限期等待 避免“活锁” 避免“活锁” 按队列实施封锁 T1:事务A共享封锁资源S T2:事务B试图独占封锁资源S,等待 T3:事务C在A释放封锁S之前申请对S的共享封锁,由于事务B已经在等待S,所以事务C排队等待 封锁与隔离级别 封锁的目的是隔离事务,保证事务之间不互相干扰; 不同的封锁机制和事务管理方式实际对应着不同的隔离级别。 隔离级别可划分为: 未提交读 提交读 可重复读 可串行化 未提交读( READ UNCOMMITTED ) 事务隔离的最低级别,仅可保证不读取物理损坏的数据,甚至不介意读“脏”数据。 对应封锁的NOLOCK,即读之前不加任何封锁。 提交读(READ COMMITTED) 默认级别,可以保证不读取“脏”数据。 对应TABLOCK封锁,即读之前加共享封锁,读完之后即自动释放封锁。 可重复读(REPEATABLE READ) 可以保证读一致性,避免不一致分析问题。 对应TABLOCK+HOLDLOCK封锁,即读之前加共享封锁,并将封锁保持到事务结束。 可串行化(SERIALIZABLE) 事务隔离的最高级别,事务之间完全隔离;如果事务在可串行化隔离级别上运行,则可以保证任何并发重叠事务均是串行的。 根据情况对应TABLOCKX或UPDLOCK封锁,保证增、删、改操作不受其他事务干扰。 设置隔离级别的命令 SET TRANSACTION ISOLATION LEVEL { READ COMMITTED | READ UNCOMMITTED | REPEATABLE READ | SERIALIZABLE } 封锁与隔离级别 可以通过指定隔离级别或对数据资源实施封锁达到事务隔离的目的; 封锁是实现并发操作的传统方法(在SQL标准中没有提及封锁),适当的运用封锁并保证高并发操作性能是一件非常复杂的工作,这需要用户深入了解各种封锁的相容性,并设计封锁的调度策略; SQL标准中规定了事务的隔离级别,即未提交读、提交读、可重复读和可串行化,隔离级别解决了并发事务可能产生的丢失更新问题、未提交依赖问题、不一致分析问题和幻象读问题,其中为了避免丢失更新问题,事务必须运行在可重复读或可串行化隔离级别。 用户可以根据事务的需要设定隔离级别,结果由数据库管理系统控制封锁和进行并发操作调度。 封锁与隔离级别 在实际应用中,也可以将隔离级别和封锁结合起来使用。例如,如果指定隔离级别是可重复读,则SQL会话中所有SELECT语句的锁定行为都运行于该隔离级别上,并一直保持有效,直到会话终止或者将隔离级别设置为另一个级别。如果必要,可以通过指定表级封锁来替
显示全部
相似文档