数据库中的并发

来源:互联网 发布:java jdk是什么 编辑:程序博客网 时间:2024/06/05 07:57

简介

所谓并发操作,是指在多用户共享系统中,许多用户可能同时对同一数据进行操作。

并发操作带来的问题是数据的不一致性,主要有三类:丢失更新、不可重复读和读脏数据。主要原因是事务的并发操作破坏了事务的隔离性。DBMS的并发控制子系统负责协调并发事务的执行,保证数据库的完整性不受破坏,避免用户得到不正确的数据。

并发操作带来的问题

并发操作带来的数据不一致性有三类:丢失更新、不可重复读和读脏数据,如下图:

Concurrency Example

  1. 丢失更新

    如上图第一种情况所示,事务T1和T2都在对数据A做加一操作,事务T1在t5时刻将修改后的A值写入数据库。但是事务T2在T6时刻把它对A加一之后的值16写入了数据库。两个事务对A的加一操作都执行成功,但A的值实际只增加了1,丢失了一次对数据的更新。原因就在于T1对数据库的修改被T2事务覆盖而丢失了,破坏了事务的隔离性。

  2. 不可重复读

    如图中第二种情况所示,事务T1读取A、B的值后进行运算,事务T2修改了B的值并在t6时刻写入了数据库。之后事务T1又重新对之前的运算进行验算,得到了和之前不一样的结果,导致验算失败。这同样也是事务T2干扰了事务T1的独立性。

  3. 读脏数据

    如图中第三种情况所示,事务T1对数据C修改之后,在t4时刻事务T2读取修改后的C值进行相关的操作,然后事务T1回滚,C恢复了原来的值,事务T2对C做的操作是无效的,它读到的是C在无效状态下的值。

并发控制技术

在事务并行处理的过程中对相同的数据进行访问,导致了数据的不一致性。解决问题的方法可以从保证事务的隔离性入手。

封锁

并发控制的主要技术是封锁,基本的封锁类型有排它锁(简称X锁或写锁)和共享锁(简称S锁或读锁)。下面分别进行介绍:

  1. 排它锁

    若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它事务都不能再对A加任何类型的锁,直到T释放A上的锁。

  2. 共享锁

    若事务T对数据对象A加上了S锁,则只允许T读取A,但不能修改A,其它事务只能再对A加S锁,直到T释放A上的S锁。这样,可以保证其它事务可以读A,但在T释放A上的S锁之前不能对A进行任何修改。

三级封锁协议

和封锁相关的还有三级封锁协议:

  1. 一级封锁协议

    事务在修改数据A之前必须先对其加X锁,直到事务结束才释放。事务结束包括正常结束(Commit)和非正常结束(Rollback)。一级封锁协议可以解决丢失更新的问题。

  2. 二级封锁协议

    在记忆封锁协议的基础之上,加上事务T在读数据A之前必须先对其加S锁,读完之后即可释放S锁。二级封锁协议可以解决读脏数据的问题。但是,由于二级封锁协议读完了数据之后即可释放S锁,在没有加S锁的间隙(见上图中的第二种情况),数据有可能被其它事务修改,所以不能保证可重复读。

  3. 三级封锁协议

    在一级封锁协议的基础上,加上事务T在读数据A之前必须先对其加上S锁,直到事务结束才释放S锁。三级封锁协议除了防止读脏数据和丢失修改之外,还进一步防止了不可重复读。

相关概念

死锁和活锁

  • 活锁

    活锁是指当事务T1封锁了数据A,事务T2请求封锁数据A,于是T2等待,当T1释放了A上的封锁之后,系统首先批准了T3对A的封锁请求,于是T2仍等待,当T3释放了A上的封锁之后,系统又批准了T4的封锁请求,以此类推,使得T2可能永远等待的现象。

  • 死锁

    死锁是指两个以上的事务分别请求封锁对方已经封锁的数据,导致长期等待而无法继续运行下去的现象。

并发调度的可串行性

多个事务的并发执行时正确的,当且仅当其结果与以某一次序串行地执行它们时的结果相同,称这种调度策略是可串行化的调度。

可串行性是并发事务正确性的准则,按照这个准则规定,一个给定的并发调度,当且仅当它是可串行化的才认为是正确调度。

两段封锁协议

两段封锁协议是指所有事务必须分两个阶段对数据项加锁和解锁。即事务分为两个阶段,第一阶段是获得封锁,事务可以获得任何数据项上的任何类型的锁,但不能释放;第二阶段是释放封锁,事务可以释放任何数据项上的任何类型的锁,但是不能申请加锁。

封锁的粒度

封锁对象的大小称为封锁的粒度。封锁的对象可以是逻辑单元(如属性、元组、关系、索引项、整个索引乃至整个数据库),也可以是物理单元(如数据页或者索引页)。

0 0
原创粉丝点击