精华内容
下载资源
问答
  • 数据库并发控制技术

    千次阅读 2018-08-25 14:27:19
    事务处理技术主要包括数据库恢复技术和并发控制技术。本篇博文主要总结下并发控制技术。 事务:是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。例如,在关系数据库中,...

    事务是一系列的数据库操作,是数据库应用程序的基本逻辑单元,也是恢复和并发控制的基本单位。

    事务处理技术主要包括数据库恢复技术并发控制技术。本篇博文主要总结下并发控制技术。

    事务:是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。例如,在关系数据库中,一个事务可以是一条SQL语句、一组SQL语句或整个程序。一般来说,一个程序中包含多个事务。

    ACID,是指在可靠数据库管理系统(DBMS)中,事务(transaction)所应该具有的四个特性:

    A:原子性(Atomicity): 事务是一个或多个行为捆绑在一起组成一个单独的工作单元,事务中的动作要不都发生,要不都不发生。

    C:一致性(Consistent): 即在事务开始之前和结束之后,数据库的完整性约束没有被破坏。

      数据库层面:在一个事务执行前和执行后,数据会符合你设置的约束(例如unique约束,foreign key约束,check约束等)和触发器设置.由数据库进行保证.

      业务层面:保持业务的一致性.需要由开发人员进行保证.

    I:隔离性(Isolation):指的是在并发环境中,事务之间互相影响的程度(即并发事务间数据的可见程度).当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间.由并发事务所做的修改必须与任何其他并发事务所做的修改隔离.事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据.。

    D:持续性(Durability): 也叫永久性,指一旦事务完成,事务的结果应该持久化,用来保证即使系统崩溃也不会破坏事务的结果。

    保证事务ACID特性是事务管理的重要任务。事务ACID特性可能遭到破坏的因素有:

    (1)多个事务并行运行时,不同事务的操作交叉执行。

    (2)事务在运行过程中被强行停止。

    并发操作带来的数据不一致性包括丢失修改、不可重复读和读“脏”数据。

    No.1 丢失修改(或叫丢失更新)

    如果两个事务都要更新数据库一个字段X,X=100;

    事务A 事务B
    读取X=100  读取X=100
    写入x=X+100 写入x=X+200
    事务结束x=200  事务结束x=300
      最后x=300
     

    两个不同的事务同时获得了相同的数据,又都对这个数据进行了修改,那么先提交的事务的更新就会被后提交事务的更新覆盖掉,叫做丢失更新。

    No.2 不可重复读

    一个事务执行期间,在自己没有更新数据库的情况下,同一个查询操作在执行一次或多次的情况下,结果应该是一致的。

    事务A 事务B
    读取X=100 读取X=100
    读取X=100  写入x=X+100
      事务结束, x=200
    读取X=200
    (此时,在同一个事务A中,读取的X值发生了变化!)
     
    事务结束  
     

    这种情况事务A多次读取数据出现不一致的结果。

    摘自王珊老师的《数据库系统概论》(第5版)的解释:不可重复读包括三种情况(后两种情况也称为幻影现象或幻读):

    (1):事务T1读取某一数据之后,事务T2对其进行了修改,当事务T1再次读该数据时,得到与前一次不同的值.如上所示。

    (2):事务T1按一定条件从数据库中读取了某些数据记录后,事务T2删除了其中部分记录,当T1再次按照相同条件读取数据时,发现某些记录神秘的消失了。

    (3):事务T1按一定条件从数据库中读取了某些数据记录后,事务T2插入了一些记录,当T1再次按照相同条件读取数据时,发现多了一些记录。

    No.3 脏读(读脏数据,未提交读)

    事务A    事务B
      写入x=X+100 (x=200)
    读取X=200 (读取了事务B未提交的数据)    
      事务回滚x=100 
      事务结束x=100
    事务结束

    事务读取了未提交的数据,如图 事务B可能出现未提交或者提交不成功的情况而进行回滚,这就导致事务A读取了错误的数据,也叫脏数据。

    并发控制的主要技术有封锁(locking)、时间戳(timestamp)、乐观控制法(optimistic sheduler)和多版本并发控制(multi-version concurrency control,MVCC)等。

    下面主要讲封锁方法。

    封锁是实现并发控制的一个非常重要的技术。基本的封锁类型有两种:排他锁(X锁)共享锁(S锁)。

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

    共享锁又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事物只能再对A加S锁,而不能加X锁。

    在运用 排他锁 和 共享锁 对数据对象加锁时,还需要约定一些规则,例如何时申请 排他锁 或 共享锁、持锁时间、何时释放等。称这些规则为封锁协议(Locking Protocol)。对封锁方式规定不同的规则,就形成了各种不同的封锁协议。不同的封锁协议对应不同的隔离级别

    在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同:

    A. 未授权读取(Read uncommited):允许脏读取,但不允许丢失修改。

    对应一级封锁协议:一级封锁协议是:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。事务结束包括正常结束(COMMIT)和非正常结束(ROLLBACK)。 

    B. 授权读取(Read Committed):允许不可重复读取,但不允许脏读取和丢失修改。这可以通过“瞬间共享读锁”和“排他写锁”实现。

    对应二级封锁协议:二级封锁协议是:一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁(瞬间S锁)。

    C. 可重复读取(Repeatable Read):禁止不可重复读取和脏读取和丢失修改,但是有时可能出现幻影数据。这可以通过“共享读锁”和“排他写锁”实现。

    对应三级封锁协议:三级封锁协议是:一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放

    D. 序列化(Serializable):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。

     四级封锁协议是对三级封锁协议的增强,其实现机制也最为简单,直接对事务中所读取或者更改的数据所在的表加表锁,也就是说,其他事务不能读写该表中的任何数据。这样所有的脏读,不可重复读,幻读,都得以避免!

     

    展开全文
  • 本篇博客介绍如何进行并发控制。 ——封锁。   1,封锁 (1)封锁就是事务T在对某数据对象(例如:表、记录)操作之前,先向系统发出请求,对其加锁 (2)加锁后事务T就对数据对象了一定的控制,在事务T释放它的锁...

    上篇博客通过一些实例介绍了并发导致的数据不一致一系列问题——丢失修改、读脏数据、不可重复读


     

    本篇博客介绍如何进行并发控制。

    ——封锁。

     

    1,封锁

    1)封锁就是事务T在对某数据对象(例如:表、记录)操作之前,先向系统发出请求,对其加锁

    2)加锁后事务T就对数据对象有了一定的控制,在事务T释放它的锁之前,其他的事务不能更新此数据对象

     

    2,封锁类型

    不同的锁有不同的控制功能;即,一个事务对数据对象加锁后可有怎样的控制由它的封锁类型决定。

    1)排他锁(简称X锁,或写锁)

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

    b.功能:保证其他事务在事务T释放数据对象A上的锁之前不能在读和修改A

    2)共享锁(简称S锁,或读锁)

    a.含义:若事务T对数据对象A加上S锁,则其他事务只能再对AS锁,而不能加X锁,直到T释放A上的S

    b.功能:保证其他事务可以读数据对象A,但在事务T释放A上的S锁之前不能对A做任何修改、

     

    关注点在哪里,一级封锁协议的关注点是事务修改的数据,二级和三级是事务读取的数据

     

    3,三级封锁协议分别解决的问题

    1)一级:

    a.内容:事务T在修改数据对象A之前必须对其加X锁,直到事务结束才释放。

    b.可解决的问题:“丢失修改”问题

    T1

    T2

    解释

    Xlock A

     

    事务T1在读A进行修改之前先对AX

    R(A)=16

     

     

     

    Xlock A

    T2再请求对AX锁时被拒绝

    AA-1

    等待

     

     

      T2只能等待T1释放A上的锁后T2获得对AX

     

        W(A)=15

    等待

     

        Commit

    等待

     

        Unlock A

    等待

     

    获得Xlock A

     

     

    R(A)=15

    这时T2读到的A已经是T1更新过的值15

     

    AA-1

     

    T2按此新的A值进行运算,并将结果值A=14送回到磁盘。避免了丢失T1的更新。

    W(A)=14

     

     

    Commit

     

     

    Unlock A

     

    思考:一级封锁协议为什么不能解决脏读和不可重复读问题?

    在一级封锁协议中,如果仅仅是读数据不对其进行修改,是不需要加锁的,所以它不能保证可重复读和不读“脏”数据。即,事务1对R加了排他锁,对数据R进行了修改,若事事务2对R申请锁,则会wait;若事务2不对R申请任何锁,则即使事务1对R加了排他锁,事务2也会无视,可以读!所以不能解决脏读和不可重复读问题
     

    2)二级:

    a.内容:在一级封锁协议的基础上,另外加上事务T在读取数据对象A之前必须对其加S锁,读完后立即释放

    b.可以解决的问题:“丢失修改”、“读脏数据”问题

    T1

    T2

    解释

     Xlock C

     

    事务T1在对C进行修改之前,先对CX锁,修改其值后写回磁盘

     

    R(C)=100

     

     

    CC*2

     

     

    W(C)=200

     

     

    Slock C

     

     

    T2请求在C上加S锁,因T1已在C上加了X锁,T2只能等待

     

     

    等待

     

    ROLLBACK

    等待

     

    (C恢复为100)

    等待

    T1因某种原因被撤销,C恢复为原值100

     

    Unlock C

    等待

     

    获得Slock C

     

     

    R(C)=100

    T1释放C上的X锁后T2获得C上的S锁,读C=100。避免了T2读“脏”数据

     

    Commit C

     

     

    Unlock C

     


     

    思考:为什么二级封锁不能解决“不可重复读”问题?

    ——事务1读取数据时加上共享锁后(这样在事务1读取数据的过程中,其他事务就不会修改该数据),

    不允许任何事物操作该数据,只能读取,之后1如果有更新操作,那么会转换为排他锁,其他事务更无权参与进来读写,

    这样就防止了脏读问题。但是当事务1读取数据过程中,有可能其他事务(例如事务2)也读取了该数据,事务1读取完毕后共享锁释放(此时事务1还未完),

    此时事务2修改数据,修改完毕提交事务,那么事务1再次读取数据时候发现数据不一致,就会出现不可重复读问题,

    所以这样不能够避免不可重复读问题。

     

    3)三级:

    a.内容:在一级封锁协议的基础上,另外加上事务T在读取数据对象A之前必须对其加S锁,直到事务结束才释放

    b.可以解决的问题:“丢失修改”、“读脏数据”、“不可重复读”问题

    T1

    T2

    解释

    1.  Slock A

     

    事务T1在读AB之前,先对ABS锁;

    其他事务只能再对ABS锁,而不能加X锁,即其他事务只能读AB,而不能修改

     

     

    Slock B

     

     

    R(A)=50

     

     

    R(B)=100

     

     

    求和=150

     

     

    Xlock B

     

     

     

     

    T2为修改B而申请对BX锁时被拒绝只能等待T1释放B上的锁

     

    T1为验算再读AB,这时读出的B仍是100,求和结果仍为150,即可重复读

     

     

     

     

     

    T1结束才释放AB上的S锁。T2才获得对BX

     

    等待

     

     

    等待

     

     R(A)=50

    等待

     

    R(B)=100

    等待

     

    求和=150

    等待

     

    Commit

    等待

     

    Unlock A

    等待

     

    Unlock B

    等待

     

    获得XlockB

     

     

    R(B)=100

     

     

    BB*2

     

    W(B)=200

     

     

    Commit

     

     

    Unlock B

     


    注:关注点在哪里?

    —— 一级封锁协议的关注点是事务修改的数据,二级和三级是事务读取的数据

     

    4,总结:

    1)锁的相容矩阵:


    (如果R上加了X锁后,就不能再加任何锁!如果R上加了S锁后,只能再加S锁而不能再加X锁!)

     

    2

     

    X

    S

     

    无丢失修改

    无污读

    可更新

     

    事务结束释放

    事务结束释放

    读完释放

     

     

     

    一级封锁协议

     

     

     

     

    二级封锁协议

     

     

    三级封锁协议

     


    展开全文
  • 并发控制

    千次阅读 2018-08-02 18:17:07
    所谓事务,是指用户定义的一个数据库操作序列,这些操作要么全做,要么全不做...事务是并发控制的基本单位,保证事务ACID特性是事务处理的重要任务。 并发操作带来的数据的不一致性问题: 1.丢失修改 两个事务T1...

    所谓事务,是指用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。
    事务具有四个特性:
    1.原子性 2.一致性(Consistency) 3.隔离性(Isolation)持续性(Durability)

    并发控制概述

    事务是并发控制的基本单位,保证事务ACID特性是事务处理的重要任务。
    并发操作带来的数据的不一致性问题:
    1.丢失修改
    两个事务T1和T2读入同一组数据并修改,T2提交的结果破坏了T1提交的结果,导致T1的修改被丢失。
    2.不可重复读
    不可重复读是指事物T1读取数据后,事务T2执行更新操作,使T1无法再前一次读取的结果。不重复读包括三种结果:
    (1)事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读该数据时,得到与前一次不同的值。
    (2)事务T1按一定条件从数据库中读取某些数据记录后,事务T2删除了其中部分记录,当T1再次按相同条件读取数据时,发现某些记录神秘消失了。
    (3)事务T1按一定条件从数据库中读取某些数据记录后,事务T2插入了一些记录,当T1再次按照相同条件读取数据时,发现多了一些记录。
    后两种不可重复读有时也称为幻影现象。
    3.读脏数据(Dirty Read)
    读脏数据是指事物T1修改某一数据,并将其写会磁盘,事物T2读取同一数据后,T1由于某种原因被撤销,这时T1已修改过的数据被恢复原值,T2读到的数据与数据库中的数据不一致,则T2读到的数据就为“脏数据”。
    产生上述三类数据不一致的主要原因是并发操作破坏了事务的隔离性。
    并发控制的主要技术有封锁(Locking)、时间戳(Timestamp)和乐观控制法,商用的DBMS一般都采用封锁方法。

    封锁

    所谓封锁就是事务T在对某个数据对象例如表、记录等操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其他的事务不能更新此数据对象。
    基本的封锁类型有两种:
    1.排它锁(Exclusive Locks),简称X锁
    2.共享锁(Share Locks),简称S锁
    排它锁又称写锁。若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。
    共享锁又称读锁。若事务T对数据对象A加上S锁,则事务T可以读A但是不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。

    活锁和死锁

    活锁

    如果事务T1封锁了数据R,事务T2又请求封锁R,于是T2等待。T3也请求封锁R,当T1释放了R上的锁后系统首先批准了T3的请求,T2仍然等待。然后T4又请求封锁R,当T3释放了R上的封锁之后系统又批准了T4的请求…T2有可能永远等待下去,这就是活锁的情形。
    避免活锁采用的方法是先来先服务的策略。

    死锁

    1.死锁的预防

    通常有两种方法:1.一次封锁法 2.顺序封锁法
    一次封锁法:要求每个事务必须一次性将所有要使用的数据全部加锁,否则就不能继续执行。
    存在问题:1.一次就讲以后要用到的全部数据加锁,扩大了封锁的范围,从而降低了系统的并发度。
    2.数据库中的数据是不断变化的,原来不要求封锁的数据,在执行过程中可能会变成封锁对象,所以很难先景区地确定每个事务索要封锁的数据对象。
    顺序封锁法:预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实行封锁。
    存在问题:1.数据库系统中封锁的数据对象极多,并且随数据的插入、删除等操作不断变化,要维护这样的资源的封锁顺序非常困难,成本很高。
    2.事务的封锁请求可以随着事务的执行而动态地决定,很难事先确定每一个事务要封锁那些对象,因此也很难按规定的顺序去施加封锁。
    DBMS在解决死锁的问题上普遍采用的是诊断并解除死锁的方法

    2.死锁的诊断与解除

    1.超时法
    如果一个事务的等待时间超过了规定的时限,就认为发生了死锁。
    不足:1.有可能误判死锁,事务因为其他原因使等待时间超过时限,系统会误认为发生了死锁。
    2.时限若设置得太长,死锁发生后不能及时发现。
    2.等待图法
    事务等待图是一个有向图G=( T, U).T为结点的集合,每个结点表示正在运行的事务,U为边的集合,每条边表示事务的等待情况。
    事务等待情况动态反应了所有事务的等待情况。并发控制子系统周期性地生成事务等待图,并进行检测。如果发现图中存在回路,则表示系统中出现了死锁。
    DBMS的并发控制子系统一旦检测到系统中存在死锁,就要设法解除。通常采用的方法是选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有的锁,使其他事务得以继续运行下去。

    并发调度的可串行性

    DBMS对并发事务不同的调度可能会产生不同的结果,那么什么样的调度是正确的呢?显然,串行调度是正确的。执行结果等价于串行调度的调度也是正确的。这样的调度叫可串行化调度。

    可串行化调度

    定义:多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行的执行这些事务时的结果相同,称这个调度策略是可串行化的。
    可串行性是并发事务正确执行的准则。

    冲突可串行化调度

    冲突操作是指不同的事务对同一个数据的读写操作和写写操作:
    Ri(x)与Wj(x) //事务Ti读x,Tj写x
    Wi(x)与Wj(x) //事务Ti写x,Tj写x
    其他操作是不冲突操作。
    一个调度Sc在保证冲突操作的次序不变的情况下,通过交换两个事务不冲突操作的次序得到另一个调度Sc’,如果Sc’是串行的,称调度Sc为冲突可串行化的调度。一个调度是冲突可串行化,一定是可串行化的调度。
    冲突可串行化调度是可串行化调度的充分条件,不是必要条件。还有不满足冲突可串行化条件的可串行化调度。

    两段锁协议

    在运用封锁方法时,对数据对象加锁时需要约定一些规则,例如何时申请封锁、持所时间、何时释放封锁等。这些规则被称为封锁协议。
    所谓两段锁协议是指所有事务必须分两个阶段对数据项加锁和解锁:
    1.在对任何数据进行读、写操作之前,首先要申请并获得对该数据的加锁
    2.在释放一个封锁之后,事务不再申请和获得任何其他封锁
    两段锁的含义是,事务分为两个阶段,第一个阶段是获得封锁,也称为扩展阶段。在这阶段,事务可以申请获得任何数据项上的任何类型的锁,但是不能释放任何锁。第二个阶段是释放封锁,也称为收缩阶段。在这阶段,事务可以释放任何数据项上的任何类型的锁,但是不能再申请任何锁。
    事务遵守两段锁协议是可串行化的充分条件,而不是必要条件。
    要注意两段锁协议和防止死锁的一次封锁法的异同之处。一次封锁法要求每个事物必须一次将所有要使用的数据全部加锁,否则就不能继续执行。因此一次封锁遵守两段锁协议;但是两段锁协议并不要求事务必须将所有要是有的数据全部加锁,因此遵守两段锁协议的事务可能发生死锁。

    封锁的粒度

    封锁对象的大小称为封锁粒度。封锁对象可以是逻辑单元,也可以是物理单元。以关系数据库为例,封锁对象可以是这样一些逻辑单元:属性值、属性值的集合、元组、关系、索引项、整个索引直至整个数据库;也可以是这样一些物理单元:页、物理记录等。
    如果在一个系统中同时支持多种封锁粒度供不同的事务选择是比较理想的,这种封锁方法称为多粒度封锁。

    多粒度封锁

    多粒度树:多粒度树的根节点是整个数据库,表示最大的数据粒度。叶节点表示最小的数据粒度。
    多粒度封锁协议允许多粒度树种的每个节点被独立地加锁。对一个结点加锁意味着这个结点的所有后裔结点也被加以同样类型的锁。因此,在多粒度封锁中一个数据对可能一两种方式加锁,显示封锁和隐式封锁。
    显示封锁是应事务的要求直接加到数据对象上的封锁;
    隐式封锁是该数据对象没有独立加锁,是由于其上级结点加锁而使该数据对象加上了锁。
    一般地,对某个数据对象加锁,系统要检查该数据对象是哪个有误显示封锁与之冲突;还要检查其所有上级结点,看本事务的显示封锁是否与该数据对象上的隐式封锁冲突;还要检查所有下级结点,看上面的显示封锁是否与本事务的隐式封锁冲突。

    意向锁

    意向锁的含义是如果对一个结点加意向锁,则说明该结点的下层结点正在被加锁;对任一结点加锁时,必须先对他的上层结点加意向锁。
    意向共享锁(IS锁)、意向排它锁(IX锁)、共享意向排它锁(SIX锁)
    IS锁
    如果对一个数据对象加S锁,表示它的后裔结点拟(意向)加S锁。
    IX锁
    如果对一个数据对象加IX锁,表示它的后裔结点拟(意向)加X锁。
    SIX锁
    如果对一个数据对象加SIX锁,表示对它加S锁,再加IX锁,即SIX= S+IX。
    具有意向锁的多粒度封锁方法中任一事务T要对一个数据对象加锁,必须先对它的上层结点加意向锁。申请封锁时应该按自上而下的次序进行;释放封锁时应该按自下而上的顺序进行。

    基于时间戳的协议

    另一种决定事务可串行化次序的方法是事先选定事务的次序。其中最常用的方法是时间戳排序机制。

    时间戳

    对于系统中每个事务Ti,我们把一个唯一的固定时间戳和它联系起来,此时间戳记为TS(Ti)。该时间戳是在事务Ti开始执行前由数据库系统赋予的。若事务Ti已赋予时间戳TS(Ti),此时有一种新事务Ti进入系统,则TS(Ti) < TS(Tj)。实现这种机制可以采用下面这两个简单的办法:
    1.使用系统时钟的值作为时间戳:即事务的时间戳等于该事务进入系统时的时钟值。
    2.使用逻辑计数器,每赋予一个时间戳,计数器增加计数,即事务的时间戳等于该事务进入系统时的计数器值。
    要实现这个机制,每个数据项Q需要与两个时间戳值相关联:
    W-timestamp(Q)表示成功执行write(Q)的所有事务的最大时间戳
    R-timestamp(Q)表示成功执行read(Q)的所有事务的最大时间戳。

    时间戳排序协议

    保证任何有冲突的read或write操作按时间戳顺序执行。该协议运作方式如下:
    1.假设事务Ti发出read(Q)
    a.若TS(Ti) < W-timestamp(Q),则Ti需要读入的Q值已经被覆盖。因此,read操作被拒绝。Ti回滚。
    b.若TS(Ti)>=W-timestamp(Q),则执行read操作,R-timestamp(Q)被设置为R-timestamp(Q)与TS(Ti)两者的最大值。
    2.假设事务Ti发出write(Q)
    a.若TS(Ti) < R-timestamp(Q),则Ti产生的Q值是先前所需要的值,且系统已假定该值不会再产生。因此,write操作被拒绝,Ti回滚。
    b.若TS(Ti) < W-timestamp(Q),则Ti时图写入的Q值已经过时。因此,write操作被拒绝,Ti回滚。
    c.其他情况,系统执行write操作,将W-timestamp(Q)设置为TS(Ti)。
    如果事务Ti由于发出read或write操作而被并发控制机制回滚,则系统赋予它新的时间戳并重新启动。
    时间戳排序协议保证冲突可串行化,这因为冲突操作按时间戳顺序进行处理。
    该协议保证无死锁,因为不存在等待的事务。但是,当一系列冲突的段事务引起长事务反复重启时,可能导致肠事务饿死的现象。如果发现一个事务反复重启,与之冲突的事务应当暂时阻塞,以使该事务能够完成。
    该协议可能产生不可恢复的调度。然而,该协议可以进行扩展,用以下几种方法之一来保证调度可恢复:
    1.在事务末端执行所有的写操作能保证可恢复性和无级联性,这些写操作必须具有下述意义的原子性:在写操作正在执行的过程中,任何事物都不允许访问已写完的任何数据项。
    2.可恢复性和无级联性也可以通过使用一个受限的发封锁形式来保证,由此,对未提交数据项的读操作被推迟到更行该数据项的事务提交之后。
    3.可恢复性可以通过跟踪为提交写操作来单独包装,一个事物Ti读取了其他事物所写的数据,只有在其他事物都提交之后,Ti才能提交。

    基于有效性检查的协议

    有效性检查协议要求每个事物Ti在其生命周期中按两个或三个阶段执行,则取决于事务是一个只读事务还是一个更新事务。
    1.读阶段:在这一阶段中,系统执行事务Ti。个数据项值被读入并保存在事务Ti的局部变量中。所有write操作都是对局部临时变量进行的,并不对数据库进行真正的更新。
    2.有效性检查阶段:对事务Ti进行有效性测试,判断是否可以执行write操作而不违反可串行性。如果事务有效性测试失败,则系统终止这个事务。
    3.写阶段:若事务Ti已通过有效性检查,则保存Ti任何写操作结果的临时就被变量值被复制到数据库中。只读事务忽略这个阶段。
    为了进行有效性检测,我们需要知道事务Ti的各个阶段何时进行。为此,我们将三个不同的时间戳与事务Ti相关联。
    1.Start(Ti):事务Ti开始执行的时间
    2.Validation(Ti):事务Ti完成读阶段并开始其有效性检查的时间
    3.Finish(Ti):事务Ti完成写阶段的时间
    我们利用时间戳Validation(Ti)的值,通过时间戳排序技术决定可串行性排序。因此,值TS(Ti) = Validation(Ti)。并且若TS(Tj) < TS(Tk),则产生的任何调度必须等价于事务Tj出现在Tk之前的某个串行调度。选择Validation(Ti)而不是Start(Ti)作为事务Ti的时间粗是因为在冲突频度很低的情况下期望有更快的响应时间。
    事务Ti的有效性测试要求任何满足TS(Tk) < TS(Tj),的事务Tj必须满足下面两条件之一:
    1.Finish(Tk) < Start(Tj)。因为Tk在Tj开始之前完成其执行,所以可串行性次序得到了保证
    2.Tk缩写的数据项集与Tj所读数据项集不相交,并且Tk的写阶段在Tj开始其有效性检查阶段之前完成。这个条件保证Tk与Tj的写不重叠。因为Tk的写不影响Tj的读,又因为Tj不可能影响Tk的读,从而保证了可串行性次序。
    在有效性检查机制中,由于事务乐观的执行,假定他们能够完成执行并且最终有效,因此也称为乐观的并发控制机制。与之相反,封锁和时间戳排序是悲观的,因为当他们检测到一个冲突时,它们强迫事务等待或回滚,即使该调度有可能是冲突可串行的。

    展开全文
  • 并发控制技术是实现事务隔离性以及不同隔离级别的关键,实现方式很多,按照其对可能冲突的操作采取的不同策略可以分为乐观并发控制和悲观并发控制两大类。 乐观并发控制:对于并发执行可能冲突的操作,假定其不会真...

    事务隔离性的实现——常见的并发控制技术

    并发控制技术是实现事务隔离性以及不同隔离级别的关键,实现方式有很多,按照其对可能冲突的操作采取的不同策略可以分为乐观并发控制和悲观并发控制两大类。

    • 乐观并发控制:对于并发执行可能冲突的操作,假定其不会真的冲突,允许并发执行,直到真正发生冲突时才去解决冲突,比如让事务回滚。(乐观锁是一种机制,主要通过程序设计来避免加锁带来的并发效率低下的问题)
    • 悲观并发控制:对于并发执行可能冲突的操作,假定其必定发生冲突,通过让事务等待(锁)或者中止(时间戳排序)的方式使并行的操作串行执行。(悲观锁的实现依靠的是数据库提供的锁机制来实现)

    基于封锁的并发控制
    核心思想:对于并发可能冲突的操作,比如读-写,写-读,写-写,通过锁使它们互斥执行。
    锁通常分为共享锁和排他锁两种类型

    1.共享锁(S):事务T对数据A加共享锁,其他事务只能对A加共享锁但不能加排他锁。
    2.排他锁(X):事务T对数据A加排他锁,其他事务对A既不能加共享锁也不能加排他锁

    基于锁的并发控制流程:

    事务根据自己对数据项进行的操作类型申请相应的锁(读申请共享锁,写申请排他锁)

    申请锁的请求被发送给锁管理器。锁管理器根据当前数据项是否已经有锁以及申请的和持有的锁是否冲突决定是否为该请求授予锁。

    若锁被授予,则申请锁的事务可以继续执行;若被拒绝,则申请锁的事务将进行等待,直到锁被其他事务释放。

    可能出现的问题:

    • 死锁:多个事务持有锁并互相循环等待其他事务的锁导致所有事务都无法继续执行。
    • 饥饿:数据项A一直被加共享锁,导致事务一直无法获取A的排他锁。

    对于可能发生冲突的并发操作,锁使它们由并行变为串行执行,是一种悲观的并发控制。

    基于时间戳的并发控制
    核心思想:对于并发可能冲突的操作,基于时间戳排序规则选定某事务继续执行,其他事务回滚。

    系统会在每个事务开始时赋予其一个时间戳,这个时间戳可以是系统时钟也可以是一个不断累加的计数器值,当事务回滚时会为其赋予一个新的时间戳,先开始的事务时间戳小于后开始事务的时间戳。

    每一个数据项Q有两个时间戳相关的字段:

    • W-timestamp(Q):成功执行write(Q)的所有事务的最大时间戳
    • R-timestamp(Q):成功执行read(Q)的所有事务的最大时间戳

    时间戳排序规则如下:

    假设事务T发出read(Q),T的时间戳为TS
    a.若TS(T)<W-timestamp(Q),则T需要读入的Q已被覆盖。此
    read操作将被拒绝,T回滚。
    b.若TS(T)>=W-timestamp(Q),则执行read操作,同时把
    R-timestamp(Q)设置为TS(T)与R-timestamp(Q)中的最大值

    假设事务T发出write(Q)
    a.若TS(T)<R-timestamp(Q),write操作被拒绝,T回滚。
    b.若TS(T)<W-timestamp(Q),则write操作被拒绝,T回滚。
    c.其他情况:系统执行write操作,将W-timestamp(Q)设置
    为TS(T)。

    基于时间戳排序和基于锁实现的本质一样:对于可能冲突的并发操作,以串行的方式取代并发执行,因而它也是一种悲观并发控制。它们的区别主要有两点:

    • 基于锁是让冲突的事务进行等待,而基于时间戳排序是让冲突的事务回滚。
    • 基于锁冲突事务的执行次序是根据它们申请锁的顺序,先申请的先执行;而基于时间戳排序是根据特定的时间戳排序规则。

    基于有效性检查的并发控制
    核心思想:事务对数据的更新首先在自己的工作空间进行,等到要写回数据库时才进行有效性检查,对不符合要求的事务进行回滚。

    基于有效性检查的事务执行过程会被分为三个阶段:

    • 读阶段:数据项被读入并保存在事务的局部变量中。所有write操作都是对局部变量进行,并不对数据库进行真正的更新。
    • 有效性检查阶段:对事务进行有效性检查,判断是否可以执行write操作而不违反可串行性。如果失败,则回滚该事务。
    • 写阶段:事务已通过有效性检查,则将临时变量中的结果更新到数据库中。

    有效性检查通常也是通过对事务的时间戳进行比较完成的,不过和基于时间戳排序的规则不一样。

    该方法允许可能冲突的操作并发执行,因为每个事务操作的都是自己工作空间的局部变量,直到有效性检查阶段发现了冲突才回滚。因而这是一种乐观的并发策略。

    基于快照隔离的并发控制
    快照隔离是多版本并发控制(mvcc)的一种实现方式。

    其核心思想是:数据库为每个数据项维护多个版本(快照),每个事务只对属于自己的私有快照进行更新,在事务真正提交前进行有效性检查,使得事务正常提交更新或者失败回滚。

    由于快照隔离导致事务看不到其他事务对数据项的更新,为了避免出现丢失更新问题,可以采用以下两种方案避免:

    • 先提交者获胜:对于执行该检查的事务T,判断是否有其他事务已经将更新写入数据库,是则T回滚否则T正常提交。
    • 先更新者获胜:通过锁机制保证第一个获得锁的事务提交其更新,之后试图更新的事务中止。

    事务间可能冲突的操作通过数据项的不同版本的快照相互隔离,到真正要写入数据库时才进行冲突检测。因而这也是一种乐观并发控制。

    关于并发控制技术的总结
    以上只是对常见的几种并发控制技术进行了介绍,不涉及特别复杂的原理的讲解。之所以这么做一是要真的把原理和实现细节讲清楚需要涉及的东西太多,篇幅太长,从作者和读者角度而言都不是一件轻松的事,所以只对其实现的核心思想和实现要点进行了简单的介绍,其他部分就一笔带过了。二是并发控制的实现的方式太过多样,基于封锁的实现就有很多变体,mvcc多版本并发控制的实现方式就更是多样,而且很多时候会和其他并发控制方式比如封锁的方式结合起来使用。
    通常使用的mySql Innodb引擎在数据库层面上使用悲观锁的方式来控制并发事物,而为了提升数据库并发的性能,程序设计时可采用乐观锁的模式,避免加锁,即在表中添加版本号或者时间戳字段通过有效性检查来作为是否可以成功提交的关键因素。

    详细可参考: https://www.cnblogs.com/taek/p/4744555.html

    故障与故障恢复技术

    为什么需要故障恢复技术
    数据库运行过程中可能会出现故障,这些故障包括事务故障和系统故障两大类

    • 事务故障:比如非法输入,系统出现死锁,导致事务无法继续执行。
    • 系统故障:比如由于软件漏洞或硬件错误导致系统崩溃或中止。

    这些故障可能会对事务和数据库状态造成破坏,因而必须提供一种技术来对各种故障进行恢复,保证数据库一致性,事务的原子性以及持久性。数据库通常以日志的方式记录数据库的操作从而在故障时进行恢复,因而可以称之为日志恢复技术。

    事务的执行过程以及可能产生的问题
    在这里插入图片描述
    事务的执行过程可以简化如下:

    • 系统会为每个事务开辟一个私有工作区
    • 事务读操作将从磁盘中拷贝数据项到工作区中,在执行写操作前所有的更新都作用于工作区中的拷贝.
    • 事务的写操作将把数据输出到内存的缓冲区中,等到合适的时间再由缓冲区管理器将数据写入到磁盘。

    由于数据库存在立即修改和延迟修改,所以在事务执行过程中可能存在以下情况:

    • 在事务提交前出现故障,但是事务对数据库的部分修改已经写入磁盘数据库中。这导致了事务的原子性被破坏。
    • 在系统崩溃前事务已经提交,但数据还在内存缓冲区中,没有写入磁盘。系统恢复时将丢失此次已提交的修改。这是对事务持久性的破坏。

    日志的种类和格式

     - <T,X,V1,V2>:描述一次数据库写操作,T是执行写操作的事务的唯一标识,X是要写的数据项,V1是数据项的旧值,V2是数据项的新值。
    
     - <T,X,V1>:对数据库写操作的撤销操作,将事务T的X数据项恢复为旧值V1。在事务恢复阶段插入。
    
     -  <T  start>: 事务T开始
    
     - <T  commit>: 事务T提交
    
     - <T  abort>: 事务T中止
    

    关于日志,有以下两条规则

    • 1.系统在对数据库进行修改前会在日志文件末尾追加相应的日志记录。
    • 2.当一个事务的commit日志记录写入到磁盘成功后,称这个事务已提交,但事务所做的修改可能并未写入磁盘

    日志恢复的核心思想

    撤销事务undo:将事务更新的所有数据项恢复为日志中的旧值,事务撤销完毕时将插入一条 “T abort” 记录。

    重做事务redo:将事务更新的所有数据项恢复为日志中的新值。

    事务正常回滚/因事务故障中止将进行redo
    系统从崩溃中恢复时将先进行redo再进行undo。

    以下事务将进行undo:日志中只包括"T start"记录,但既不包括"T commit"记录也不包括"T abort"记录.

    以下事务将进行redo:日志中包括"T start"记录,也包括"T commit"记录或"T abort"记录。

    假设系统从崩溃中恢复时日志记录如下

    <T0 start>
    <T0,A,1000,950>
    <T0,B,2000,2050>
    <T0 commit>
    <T1 start>
    <T1,C,700,600>
    

    由于T0既有start记录又有commit记录,将会对事务T0进行重做,执行相应的redo操作。
    由于T1只有start记录,将会对T1进行撤销,执行相应的undo操作,撤销完毕将写入一条abort记录。

    事务故障中止/正常回滚的恢复流程

    • 从后往前扫描日志,对于事务T的每个形如<T,X,V1,V2>的记录,将旧值V1写入数据项X中。
    • 往日志中写一个特殊的只读记录<T,X,V1>,表示将数据项恢复成旧值V1,这是一个只读的补偿记录,不需要根据它进行undo。
    • 一旦发现了日志记录,就停止继续扫描,并往日志中写一个<T, abort>日志记录。
      在这里插入图片描述

    系统崩溃时的恢复过程(带检查点)

    检查点是形如的特殊的日志记录,L是写入检查点记录时还未提交的事务的集合,系统保证在检查点之前已经提交的事务对数据库的修改已经写入磁盘,不需要进行redo。检查点可以加快恢复的过程。

    系统崩溃时的恢复过程分为两个阶段:重做阶段和撤销阶段。

    重做阶段:

    • 系统从最后一个检查点开始正向的扫描日志,将要重做的事务的列表undo-list设置为检查点日志记录中的L列表。
    • 发现<T,X,V1,V2>的更新记录或<T,X,V>的补偿撤销记录,就重做该操作。
    • 发现"T start"记录,就把T加入到undo-list中。
    • 发现"T abort"或"T commit"记录,就把T从undo-list中去除。

    撤销阶段:

    • 系统从尾部开始反向扫描日志
    • 发现属于undo-list中的事务的日志记录,就执行undo操作
    • 发现undo-list中事务的T的"T start"记录,就写入一条<T ,abort>记录,并把T从undo-list中去除。
    • undo-list为空,则撤销阶段结束

    总结:先将日志记录中所有事务的更新按顺序重做一遍,在针对需要撤销的事务按相反的顺序执行其更新操作的撤销操作。

    一个系统崩溃恢复的例子

    恢复前的日志如下,写入最后一条日志记录后系统崩溃

    <T0 start>
    <T0,B,2000,2050>
    <T2 commit>
    <T1 start>
    <checkpoint {T0,T1}>   //之前T2已经commit,故不用重做
    <T1,C,700,600>
    <T1 commit>
    <T2 start>
    <T2,A,500,400>
    <T0,B,2000>
    <T0 abort>   //T0回滚完成,插入该记录后系统崩溃
    

    在这里插入图片描述

    总结

    事务是数据库系统进行并发控制的基本单位,是数据库系统进行故障恢复的基本单位,从而也是保持数据库状态一致性的基本单位。ACID是事务的基本特性,数据库系统是通过并发控制技术和日志恢复技术来对事务的ACID进行保证的,从而可以得到如下的关于数据库事务的概念体系结构。

    下面链接是原文的,我只拷贝了部分我感兴趣的东西过来,需要了解更多的可以观看原文
    原文链接:https://www.cnblogs.com/takumicx/p/9998844.html

    MySQL事务提交过程(一) https://www.cnblogs.com/exceptioneye/p/5451960.html
    数据库日志redo和undo https://www.cnblogs.com/bobo137950263/p/9957150.html

    https://blog.csdn.net/u010719917/article/details/80428831(这篇博文中有提到innodb引擎经过优化后,最终把redo-log和undo-log合并,放到redo-log中,减少磁盘i/o操作)

    展开全文
  • 数据库并发控制

    千次阅读 2012-12-28 19:51:42
    1. 在数据库中为什么要并发控制?  答:数据库是共享资源,通常许多个事务同时在运行。  当多个事务并发地存取数据库时就会产生同时读取和/或修改同一数据的情况。若对并发操作不加控制就可能会存取和存储不...
  • 数据库并发控制之并发调度

    千次阅读 2018-10-25 01:08:22
    一、并发调度的可串行性 二、两段锁协议 三、封锁的粒度 四、其他并发控制机制
  • 并发控制习题

    2020-06-22 18:42:49
    并发控制可以保证事务的哪些特性? 数据库的一个明显的特点就是多个用户共享数据库资源,尤其是多用户可以同时存取相同的数据。在这样的系统中,在同一时刻并发运行的事务数可达数百个。若对事务的并发操作不加以...
  • 所以数据库管理系统必须提供并发控制机制。 并发控制机制的好坏是衡量一个数据 库管理系统性能的重要标志之一。     DM 用封锁机制来解决并发问题。它可以保证任何时候都可以多个正在运行的用户程序...
  • 第十一章 并发控制 1.事务并发 多用户数据库系统的存在(允许...并发控制主要技术有封锁、时间戳、乐观控制法和多版本并发控制。 4.封锁 排它锁(X锁)写锁:保证其他事务在T释放A上的锁之前,不能在读取和修...
  • 这种方法之所以称为悲观并发控制,是因为它主要用于数据争用激烈的环境中,以及发生并发冲突时用锁保护数据的成本低于回滚事务的成本的环境中。  乐观并发控制  在乐观并发控制中,用户读取数据时不锁定数据。当...
  • 数据库是一个共享资源,应该允许多个用户程序并行地存取数据,当对数据库进行并行操作时,可能出现...并发控制就是要用正确的方式调度并发操作,使一个用户事务的执行不受其他事务的干扰,从而避免造成数据的不一...
  • 概述:我们可以使用两种形式的并发控制策略:乐观并发控制和悲观并发控制。 假设martin和David同时都要编辑Customer文件。如果使用乐观锁策略,他们两个人都能得到一份文件的Copy,并且可以自由编辑文件。假设David...
  • 并发控制的方法除了封锁技术以外,还有时间戳方法、乐观控制法和多版本并发控制等。 时间戳方法 给每一个事务盖上一个时标,即事务开始执行的时间。每个事务具有唯一的时间戳,并按照这个时间戳来解决事务的冲突...
  • 并发控制是数据库中的一大重点,本文就数据库中的并发控制做简要分析和介绍。 在讨论数据库并发之前我们先引入事务的概念: 数据库事务通常包含了一个序列的对数据库的读/写操作(一个单元的一系列SQL语句的集合)。...
  • 数据库 - 并发控制

    千次阅读 2015-05-12 17:30:51
    并发控制机制的任务对并发操作进行正确调度 保证事务的隔离性 保证数据库的一致性多用户数据库系统的存在 允许多个用户同时使用的数据库系统 飞机定票数据库系统 银行数据库系统 特点:在同一时刻并发运行的...
  • 数据库并发控制机制

    千次阅读 2019-10-04 17:17:15
    wom知道事务的ACID特性被破坏的...并发控制技术主要有封锁,时间戳,乐观控制发和多版本并发控制等 1. 封锁 基本的封锁类型:排他锁(X锁,写锁)和共享锁(S锁,读锁) 数据库中的共享锁和排他锁:https://blo...
  • PageOffice并发控制

    2017-12-13 17:53:16
    并发控制 使用TimeSlice属性设置打开文档的并发控制时间,防止多个用户同时打开一个文件,出现编辑保存文件相互覆盖的问题。
  • 并发控制学习笔记

    2014-10-21 13:16:43
    封锁、时间戳、乐观并发控制和悲观并发控制并发控制主要采用的技术手段。   封锁是一项用于多用户同时访问数据库的技术,是实现并发控制的一项重要手段,能够防止当多用户改写数据库时造成数据丢失和损坏。当...
  • 6-3DBMS并发控制

    2016-06-30 13:18:41
    6-3DBMS并发控制tags:数据库 事务是并发控制的基本单位,保证事务的ACID特性是事务处理的重要人物,而事务的ACID特性可能... 并发控制主要技术有封锁,时间戳,乐观控制法和多版本并发控制. 名词解释丢失修改 两个事
  • 全面分析 MySQL并发控制

    千次阅读 多人点赞 2020-09-30 21:07:30
    本篇虽然题目说:全面分析,但是谁都知道,并发控制是一个多么庞大的概念是吧,本篇主要讲的是:MySQL的锁、存储引擎、事务处理机制。如果不是你期待的,可以省点时间啦;如果是的话,点赞收藏错不了! MyS.
  • MySQL并发控制

    千次阅读 2019-01-26 21:42:24
    如果数据库中的所有事务都是串行执行的,那么它非常容易...而并发(Concurrency)使一切事情的发生都了可能,它能够解决一定的性能问题,但是它会带来更多诡异的错误。 引入了并发事务之后,如果不对事务的执...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 263,764
精华内容 105,505
关键字:

并发控制的主要技术有哪些