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

    万次阅读 多人点赞 2018-09-21 23:52:17
    2. 交叉并发方式:在单处理机系统中,并行事务并行操作轮流交叉运行。 这种并行执行方式称为交叉并发方式。 3. 同时并方式:在多处理机系统中,每个处理机可以运行一个事务,多个处理机可以同时运行多个事务,实现...

    多事务执行方式


    多个事务如何一起执行呢?

    1. 事务串行执行:每个时刻只有一个事务运行,其他事务必须等到这个事务结束后方能运行。(事务一个接一个的运行)

    2. 交叉并发方式:在单处理机系统中,并行事务并行操作轮流交叉运行。 这种并行执行方式称为交叉并发方式

    3. 同时并方式多处理机系统中,每个处理机可以运行一个事务,多个处理机可以同时运行多个事务,实现多个事务真正的并行运行,这种并行执行方式称为同时并发方式

    以下讨论以单核处机的并发控制为主:

    在进行并发操作会带来哪些问题呢?

    并发操作会带来的数据不一致性:

    1. 丢失数据(W-W)

    两个事务T1、T2同时读入同一数据并修改,T2提交的结果破坏了T1提交的结果,导致T1的修改被丢失

    丢失修改

                 T1

               T2

    ①      R(A)=16 

     

    R(A)=16

          A=A-1

     

    W(A)=15

     

    A=A-1

     

    W(A=15)

    2. 不可重复读(R-W)

    事务T1读取某一个数据后,事务T2执行更新操作,使T1无法再现前一次读取结果,包括三种情况:

         ⑴. T2执行修改操作,T1再次读数据时,得到与前一次不同的值

        ⑵. T2执行删除操作,T1再次读数据时,发现某些记录神秘的消失了

         ⑶. T2执行插入操作,T1再次读数据时,发现多了一些记录

    (2)(3)发生的不可重复读有时也称为幻影现象。

    不可重复读

    T1

    T2

            R(A)=50

     

               R(B)=100

     

               求和=150

     

        R(B)=100

     

        B=B*2

     

        W(B)=200

    ③       R(A)=50

     

               R(B)=200

     

               求和=250

     

    3. 读“脏”数据(W-R)

    事务T1修改某一数据并将其写回磁盘,事务T2读取同一数据后,T1由于某种原因被撤销,这时被T1修改过的数据恢复原值,T2读到的数据就与数据库中的数据不一致,则T2读到的数据就为“脏”数据,即不正确的数据。

    读“脏”数据

    T1

    T2

          R(C)=100

     

             C=C*2

     

             W(C)=200

     

           R(C)=200

          ROLLBACK

     

              C恢复100

     

    如何避免发生这种数据不一致的现象?——DBMS必须提供并发控制机制

    并发控制机制的任务:对并发操作进行正确调度、保证事务的隔离性、保证数据库的一致性。

    并发控制的主要技术有:封锁时间戳乐观控制法多版本并发控制

    封锁是实现并发控制的一个有效措施,那么什么是封锁呢?

    封锁是事务T在对某个数据对象(例如表、记录等操作时)。先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其他事务不能更新此数据对象。

    封锁有哪些类型呢?

    1. 排他锁:简称X锁(又称写锁),若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何锁。直到T释放A上的锁。
    2. 共享锁:简称S锁(又称读锁),若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁为止。
    排他锁与共享锁控制方式的相容矩阵

                                T2

    T1

                       X 

     

                      S 

     

               - 

     

    X

    N

    N

    Y

    S

    N

    Y

    Y

    -

    Y

    Y

    Y

    有了封锁的类型,如何加锁才能使并发操作不会出现数据不一致现象呢?

    封锁协议:约定了对数据对象何时申请X锁或S锁持续时间何时释放等一系列规则。

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

    没有丢失修改

    T1

    T2

    ①       Xlock A

     

    ②       R(A)=16

     

    ③   

    Xlock A

    ④        A=A-1

    等待

              W(A)=15

    等待

         Commit Unlock 

    等待

    获得Xlock A

     

    R(A)=15

     

    A=A-1

     

    W(A)=14

     

    Commit Unlock A

    2. 二级封锁协议:在一级封锁协议的基础上增加事务T在读取数据数据R之前必须先对其加S锁读完后即可释放S锁

    不读“脏”数据

    T1

    T2

    ①    Xlock C

     

          R(C)=100

     

          C=C*2

     

         W(C)=200

     

    Slock C

     

    等待

    ③   ROLLBACK

    等待

           C恢复100

    等待

          Unlock C

    等待

    获得Slock C

     

    R(C)=100

     

    Commit

     

    Unlock C

    3. 三级封锁协议:在一级封锁协议的基础上增加事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。

    可重复读

    T1

    T2

     ①     Slock A

     

             Slock B

     

             R(A)=50

     

            R(B)=100

     

            A+B=150

     

    Xlock B

     

    等待

    ③     R(A)=50

    等待

           R(B)=100

    等待

           A+B=150

    等待

          Commit

    等待

         Unlock A

    等待

      Unlock B

    等待

    获得Xlock B

     

    R(B)=100

     

    B=B*2

     

    W(B)=200

     

    Commit

     

    Unlock B

    封锁协议级别越高,一致性程度越高

    不同级别的封锁协议和一致性保证

     

    X

    S

    一致性保证

     

    操作结束释放

    事务结束释放

    操作结束释放

    事务结束释放

    不丢失数据

    不读脏数据

    可重复读

    一级封锁协议

     

     

     

     

     

     

    二级封锁协议

     

     

     

    三级封锁协议

     

     

    封锁会带来哪些问题呢?

    1.  活锁:如果事务T1封锁了数据R,事务T2又请求封锁数据R,于是T2等待;T3也请求封锁数据R,当T1释放了R上的锁之后,系统首先批准了T3的请求,T2任然等待;然后T4又请求封锁R,当T3释放R上的锁之后,系统又批准了T4的请求……T2有可能永远等待,这就是活锁的情况。

    避免活锁的简单方法是:采用先来先服务策略

    活锁

    T1

    T2

    T3

    T4

    Lock R

     

     

     

    ……

    Lock R

     

     

    ……

    等待

    Lock R

     

    ……

    等待

    等待

     

    Unlock R

    等待

    等待

    Lock R

     

    等待

    获得Lock R

    等待

     

    等待

    ……

    等待

     

    等待

    ……

    等待

     

    等待

    Unlock R

    等待

     

    等待

     

    获得Lock R

     

    等待

     

    ……

     

    等待

     

    ……

    2. 死锁:如果事务T1封锁了数据R1,T2封锁了数据R2,然后T1又请求封锁R2,因T2封锁了R2,于是T1等待T2释放R2上的锁;接着T2又请求封锁R1,因T1封锁了R1,于是T2等待T1释放R1上的锁。这样就出现了T1在等待T2,而T2又在等待T1,的局面,T1、T2两个事务永远不能结束,形成死锁

    死锁

    T1

    T2

    Lock R1

     

    ……

    Lock R2

    Lock R2

    ……

    等待

    ……

    等待

    Lock R1

    等待

    等待

    等待

    等待

    等待

    等待

    解决死锁的方法:有两种思路

    1. 预防死锁的发生

            ① 一次封锁法:一次性将所有要使用的数据全部加锁,否则就不能继续执行

                存在的问题:扩大了封锁范围,降低了系统的并发度;

            ② 顺序封锁法:预先对数据对象规定一个封锁顺序,所有事务都按照这个顺序实施封锁。

                存在的问题

                  1.数据库在动态地不断变化,要维护这样的资源的封锁顺序非常困难,成本很高。

                  2.事务的封锁请求可以随着事务的执行而动态地决定,很难实现确定每一个事务要封锁哪些对象,因此很难按规定的顺序去施加封锁。

    2. 死锁的诊断与解除(普遍采用的方法)

           ① 超时法:如果一个事务的等待时间超过了规定的时限,就认为发生了死锁

               存在的问题

                    1.时间设置太短,有可能误判死锁

                    2.时间设置太长,死锁发生后不能及时发现

           ② 等待图法:事务等待图是一个有向图G=(T,U),T为结点的集合,每个结点表示正在运行的事务;U为边的集合,表示事务等待情况,若事务T1等待T2,则在T1、T2之间画一条有向边,从T1指向T2。

     

    事务等待图动态地反映了所有事务的等待情况。并发控制子系统周期性地(如每隔数秒)生成事务等待图,并进行检测。如果发现图中存在回路,则表示系统中出现了死锁。并发控制子系统一旦检测到系统中存在死锁,就要设法解除。通常采用的方法是选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有的锁,使其他事务得以运行下去。

    并发调度的可串行性

    数据库管理系统对并发事务的不同调度可能会产生不同的结果,什么样的调度是正确的呢?

    可串行化的调度是正确的

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

    什么是可串行化调度?

    多个事务的并发执行是正确的,当且仅当其结果与按某一次串行执行这些事务的结果相同,称这种调度策略为可串行化调度

    如何判断一个调度是否为可串行化的调度?

    冲突操作:不同的事务对同一数据对象的读写操作和写写操作

       Ri(x)与Wi(x)     //事务Ti读x,Tj写x,其中i≠j

    Wi(x)与Wi(x)     //事务Ti写x,Tj写x,其中i≠j

    原则:不同事务的冲突操作和同一事物的两个操作是不能交换的。

    一个调度Sc在保证冲突操作的次序不变的情况下,通过交换两个事务不冲突操作的次序得到另一个调度Sc’,如果Sc’是串行的,称调度Sc为冲突可串行化的调度若一个调度是冲突可串行化的,则一定是可串行化调度

    例:Sc=r1(A)w1(A)r2(A)w2(A)r1(B)w1(B)r2(B)w2(B)

        Sc=r1(A)w1(A)r2(A) r1(B)w1(B) w2(A)r2(B)w2(B)

        Sc=r1(A)w1(A) r1(B)w1(B) r2(A)w2(A)r2(B)w2(B)

    注:冲突可串行化调度是可串行化调度的充分条件,不是必要条件、还有不满足冲突可串行化条件的可串行化调度。

    数据库管理系统如何保证调度是可串行化的呢?

    两段锁协议:所有事务必须分成两个阶段对数据项加锁和解锁。

    •       在对任何数据进行读、写操作之前,首先要申请并获得对该数据的封锁;
    •       在释放一个封锁之后,事务不在申请和获得任何其他锁。

    所谓两段是指,事务分为两个阶段:

                           第一阶段是获得封锁,也称为扩展阶段;

                           第二阶段是释放阶段,也称为收缩阶段

    结论:如果并发执行的所有事务遵循两段锁协议,那么对这些事务的任何调度都是可串行化调度

     

    什么是多粒度封锁?

    封锁的粒度:封锁对象的大小

    在一个系统中同时支持多种封锁粒度供不同的事务选择是比较理想的,这种方法称为多粒度封锁。

    封锁的对象有哪些?

    1.  物理单元:页(数据页或索引页)、物理记录等
    2.  逻辑单元:属性值、属性值的集合、元组、关系、索引项、整个索引、整个数据库

    如何进行封锁的?

    多粒度树:根节点是整个数据库,表示最大的数据粒度,叶节点表示最小的封锁粒度。

    多粒度封锁协议允许多粒度树中的每个结点被独立的加锁,对每一个结点加锁(显式封锁)意味着这个结点的所有后裔结点也被加以同样类型的锁(隐式封锁)。

    对某个数据加锁时,系统要检查该数据对象上有无显示封锁与之冲突,同时还要上下检查是否存在隐式封锁,这样的检查效率太低,因此提出了——意向锁

    意向锁:如果对一个结点加意向锁,则说明该结点的下层结点正在被加锁;对任意一结点加锁时,必须先岁它的上层结点加意向锁。

    意向锁有哪些种类?

    IS锁(意向共享锁):如果对一个数据对象加IS锁,表示它的后裔结点拟(意向)加S锁。

    IX锁(意向排他锁):如果对一个数据对象加IX锁,表示它的后裔结点拟(意向)加X锁。

    SIX锁(共享意向排他锁):如果对一个数据对象加SIX锁,表示对它加S锁,再加IX锁,即SIX=S+IX。

    数据锁的相容矩阵

                        T2

    T1

    S

    X

    IS

    IX

    SIX

    -

    S

    Y

    N

    Y

    N

    N

    Y

    X

    N

    N

    N

    N

    N

    Y

    IS

    Y

    N

    Y

    Y

    Y

    Y

    IX

    N

    N

    Y

    Y

    N

    Y

    SIX

    N

    N

    Y

    N

    N

     

    -

    Y

    Y

    Y

    Y

    Y

    Y

    申请封锁时应该按自上而下的次序进行,释放封锁时应该按自下而上的次序进行

    晚安\( ̄︶ ̄)↗

     

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

    千次阅读 2019-04-16 11:05:20
    概述 1. 什么是并发控制? 数据库是一个共享资源,可以提供多个用户使用。这些用户程序可以一个一个地串行执行...因此,为了充分利用数据库资源,发挥数据库共享资源的特点,应该允许多个用户并行地存取数据库。但这...

    概述

    1. 什么是并发控制?

    数据库是一个共享资源,可以提供多个用户使用。这些用户程序可以一个一个地串行执行,每个时刻只有一个用户程序运行,执行对数据库的存取,其他用户程序必须等到这个用户程序结束以后方能对数据库存取。但是如果一个用户程序涉及大量数据的输入/输出交换,则数据库系统的大部分时间处于闲置状态。因此,为了充分利用数据库资源,发挥数据库共享资源的特点,应该允许多个用户并行地存取数据库。但这样就会产生多个用户程序并发存取同一数据的情况,若对并发操作不加控制就可能会存取和存储不正确的数据,破坏数据库的一致性,所以数据库管理系统必须提供并发控制机制。并发控制机制的好坏是衡量一个数据库管理系统性能的重要标志之一。

    2. 为什么要进行并发控制?

    数据库是共享资源,通常有许多个事务同时在运行。当多个事务并发地存取数据库时就会产生同时读取和/或修改同一数据的情况。若对并发操作不加控制就可能会存取和存储不正确的数据,破坏数据库的一致性。所以数据库管理系统必须提供并发控制机制。
    3. 并发控制概述

    并发控制的单位――事务

    事务是数据库的逻辑工作单位,它是用户定义的一组操作序列。一个事务可以是一组SQL语句、一条SQL语句或整个程序。

    事务的开始和结束都可以由用户显示的控制,如果用户没有显式地定义事务,则由数据库系统按缺省规定自动划分事务。

    封锁

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

    封锁的粒度
    X锁和S锁都是加在某一个数据对象上的。封锁的对象可以是逻辑单元,也可以是物理单元。例如,在关系数据库中,封锁对象可以是属性值、属性值集合、元组、关系、索引项、整个索引、整个数据库等逻辑单元;也可以是页(数据页或索引页)、块等物理单元。封锁对象可以很大,比如对整个数据库加锁,也可以很小,比如只对某个属性值加锁。封锁对象的大小称为封锁的粒度(granularity)。

    封锁粒度与系统的并发度和并发控制的开销密切相关。封锁的粒度越大,系统中能够被封锁的对象就越小,并发度也就越小,但同时系统开销也越小;相反,封锁的粒度越小,并发度越高,但系统开销也就越大。
    因此,如果在一个系统中同时存在不同大小的封锁单元供不同的事务选择使用是比较理想的。而选择封锁粒度时必须同时考虑封锁机构和并发度两个因素,对系统开销与并发度进行权衡,以求得最优的效果。一般说来,需要处理大量元组的用户事务可以以关系为封锁单元;需要处理多个关系的大量元组的用户事务可以以数据库为封锁单位;而对于一个处理少量元组的用户事务,可以以元组为封锁单位以提高并发度。

    封锁协议
    封锁的目的是为了保证能够正确地调度并发操作。为此,在运用X锁和S锁这两种基本封锁,对一定粒度的数据对象加锁时,还需要约定一些规则,例如,应何时申请X锁或S锁、持锁时间、何时释放等。我们称这些规则为封锁协议(locking protocol)。对封锁方式规定不同的规则,就形成了各种不同的封锁协议,它们分别在不同的程度上为并发操作的正确调度提供一定的保证。本节介绍保证数据一致性的三级封锁协议和保证并行调度可串行性的两段锁协议,下一节将介绍避免死锁的封锁协议。

    保证数据一致性的封锁协议――三级封锁协议
    ① 1级封锁协议

    1级封锁协议的内容是:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。事务结束包括正常结束(commit)和非正常结束(rollback)。
    1级封锁协议可以防止丢失或覆盖更新,并保证事务T是可以恢复的。
    在1级封锁协议中,如果仅仅是读数据不对其进行修改,是不需要加锁的,所以它不能保证可重复读和脏读。

    ② 2级封锁协议

    2级封锁协议的内容是:1级封锁协议加上事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。
    2级封锁协议除防止了丢失或覆盖更新,还可进一步防止脏读。
    在2级封锁协议中,由于读完数据后即可释放S锁,所以它不能保证可重复读。

    ③ 3级封锁协议

    3级封锁协议的内容是:1级封锁协议加上事务T在读取数据之前必须先对其加S锁,直到事务结束才释放。
    3级封锁协议除防止丢失或覆盖更新和不脏读数据外,还进一步防止了不可重复读和幻想读。

    上述三级协议的主要区别在于什么操作需要申请封锁以及何时释放锁(即持锁时间)。

    死锁和活锁

    在这里插入图片描述
    如果事务 Tl 封锁了数据 R ,事务几又请求封锁 R ,于是几等待。几也请求封锁 R ,当 Tl 释放了 R 上的封锁之后系统首先批准了几的请求,几仍然等待。然后几又请求封锁 R ,当几释放了 R 上的封锁之后系统又批准了几的请求 … … 几有可能永远等待,这就是活锁的情形。活锁的含义是该等待事务等待时间太长,似乎被锁住了,实际上可能被激活。如果事务 Tl 封锁了数据 Rl ,几封锁了数据凡,然后 Tl 又请求封锁几,因几已封锁了几,于是 Tl 等待几释放几上的锁。接着几又申请封锁 Rl ,因 Tl 已封锁了 Rl ,几也只能等待 Tl 释放 Rl 上的锁。这样就出现了 Tl 在等待几,而几又在等待 T }的局面, T }和几两个事务永远不能结束,形成死锁。

    活锁产生的原因:当一系列封锁不能按照其先后顺序执行时,就可能导致一些事务无限期等待某个封锁,从而导致活锁。避免活锁的简单方法是采用先来先服务的策略。当多个事务请求封锁同一数据对象时,封锁子系统按请求封锁的先后次序对事务排队,数据对象上的锁一旦释放就批准申请队列中第一个事务获得锁。

    并发控制—锁和MVCC

    • 悲观并发控制
      控制不同的事务对同一份数据的获取是保证数据库的一致性的最根本方法,如果我们能够让事务在同一时间对同一资源有着独占的能力,那么就可以保证操作同一资源的不同事务不会相互影响。
      最简单的、应用最广的方法就是使用锁来解决,当事务需要对资源进行操作时需要先获得资源对应的锁,保证其他事务不会访问该资源后,在对资源进行各种操作;在悲观并发控制中,数据库程序对于数据被修改持悲观的态度,在数据处理的过程中都会被锁定,以此来解决竞争的问题。
      读写锁
      为了最大化数据库事务的并发能力,数据库中的锁被设计为两种模式,分别是共享锁和互斥锁。当一个事务获得共享锁之后,它只可以进行读操作,所以共享锁也叫读锁;而当一个事务获得一行数据的互斥锁时,就可以对该行数据进行读和写操作,所以互斥锁也叫写锁。

    共享锁和互斥锁除了限制事务能够执行的读写操作之外,它们之间还有『共享』和『互斥』的关系,也就是多个事务可以同时获得某一行数据的共享锁,但是互斥锁与共享锁和其他的互斥锁并不兼容,我们可以很自然地理解这么设计的原因:多个事务同时写入同一数据难免会发生各种诡异的问题。

    如果当前事务没有办法获取该行数据对应的锁时就会陷入等待的状态,直到其他事务将当前数据对应的锁释放才可以获得锁并执行相应的操作。

    两阶段锁协议
    两阶段锁协议(2PL)是一种能够保证事务可串行化的协议,它将事务的获取锁和释放锁划分成了增长(Growing)和缩减(Shrinking)两个不同的阶段。

    在增长阶段,一个事务可以获得锁但是不能释放锁;而在缩减阶段事务只可以释放锁,并不能获得新的锁,如果只看 2PL 的定义,那么到这里就已经介绍完了,但是它还有两个变种:

    Strict 2PL:事务持有的互斥锁必须在提交后再释放;
    Rigorous 2PL:事务持有的所有锁必须在提交后释放;

    虽然锁的使用能够为我们解决不同事务之间由于并发执行造成的问题,但是两阶段锁的使用却引入了另一个严重的问题,死锁;不同的事务等待对方已经锁定的资源就会造成死锁

    两个事务在刚开始时分别获取了 draven 和 beacon 资源上面的锁,然后再请求对方已经获得的锁时就会发生死锁,双方都没有办法等到锁的释放,如果没有死锁的处理机制就会无限等待下去,两个事务都没有办法完成。

    死锁的处理

    • 预防死锁
      有两种方式可以帮助我们预防死锁的出现,一种是保证事务之间的等待不会出现环,也就是事务之间的等待图应该是一张有向无环图,没有循环等待的情况或者保证一个事务中想要获得的所有资源都在事务开始时以原子的方式被锁定,所有的资源要么被锁定要么都不被锁定。

    但是这种方式有两个问题,在事务一开始时很难判断哪些资源是需要锁定的,同时因为一些很晚才会用到的数据被提前锁定,数据的利用率与事务的并发率也非常的低。一种解决的办法就是按照一定的顺序为所有的数据行加锁,同时与 2PL 协议结合,在加锁阶段保证所有的数据行都是从小到大依次进行加锁的,不过这种方式依然需要事务提前知道将要加锁的数据集。

    另一种预防死锁的方法就是使用抢占加事务回滚的方式预防死锁,当事务开始执行时会先获得一个时间戳,数据库程序会根据事务的时间戳决定事务应该等待还是回滚,在这时也有两种机制供我们选择,一种是 wait-die 机制:
    当执行事务的时间戳小于另一事务时,即事务 A 先于 B 开始,那么它就会等待另一个事务释放对应资源的锁,否则就会保持当前的时间戳并回滚。
    另一种机制叫做 wound-wait,这是一种抢占的解决方案,它和 wait-die 机制的结果完全相反,当前事务如果先于另一事务执行并请求了另一事务的资源,那么另一事务会立刻回滚,将资源让给先执行的事务,否则就会等待其他事务释放资源:
    两种方法都会造成不必要的事务回滚,由此会带来一定的性能损失,更简单的解决死锁的方式就是使用超时时间,但是超时时间的设定是需要仔细考虑的,否则会造成耗时较长的事务无法正常执行,或者无法及时发现需要解决的死锁,所以它的使用还是有一定的局限性。

    锁的粒度

    当我们拥有了不同粒度的锁之后,如果某个事务想要锁定整个数据库或者整张表时只需要简单的锁住对应的节点就会在当前节点加上显示(explicit)锁,在所有的子节点上加隐式(implicit)锁;虽然这种不同粒度的锁能够解决父节点被加锁时,子节点不能被加锁的问题,但是我们没有办法在子节点被加锁时,立刻确定父节点不能被加锁。

    在这时我们就需要引入意向锁来解决这个问题了,当需要给子节点加锁时,先给所有的父节点加对应的意向锁,意向锁之间是完全不会互斥的,只是用来帮助父节点快速判断是否可以对该节点进行加锁。

    乐观并发控制

    乐观并发控制也叫乐观锁,但是它并不是真正的锁,很多人都会误以为乐观锁是一种真正的锁,然而它只是一种并发控制的思想。

    • 基于时间戳的协议
      锁协议按照不同事务对同一数据项请求的时间依次执行,因为后面执行的事务想要获取的数据已将被前面的事务加锁,只能等待锁的释放,所以基于锁的协议执行事务的顺序与获得锁的顺序有关。在这里想要介绍的基于时间戳的协议能够在事务执行之前先决定事务的执行顺序。

    每一个事务都会具有一个全局唯一的时间戳,它即可以使用系统的时钟时间,也可以使用计数器,只要能够保证所有的时间戳都是唯一并且是随时间递增的就可以。

    基于时间戳的协议能够保证事务并行执行的顺序与事务按照时间戳串行执行的效果完全相同;每一个数据项都有两个时间戳,读时间戳和写时间戳,分别代表了当前成功执行对应操作的事务的时间戳。

    该协议能够保证所有冲突的读写操作都能按照时间戳的大小串行执行,在执行对应的操作时不需要关注其他的事务只需要关心数据项对应时间戳的值就可以了:

    无论是读操作还是写操作都会从左到右依次比较读写时间戳的值,如果小于当前值就会直接被拒绝然后回滚,数据库系统会给回滚的事务添加一个新的时间戳并重新执行这个事务。

    • 基于验证的协议

    乐观并发控制其实本质上就是基于验证的协议,因为在多数的应用中只读的事务占了绝大多数,事务之间因为写操作造成冲突的可能非常小,也就是说大多数的事务在不需要并发控制机制也能运行的非常好,也可以保证数据库的一致性;而并发控制机制其实向整个数据库系统添加了很多的开销,我们其实可以通过别的策略降低这部分开销。

    而验证协议就是我们找到的解决办法,它根据事务的只读或者更新将所有事务的执行分为两到三个阶段:

    在读阶段,数据库会执行事务中的全部读操作和写操作,并将所有写后的值存入临时变量中,并不会真正更新数据库中的内容;在这时候会进入下一个阶段,数据库程序会检查当前的改动是否合法,也就是是否有其他事务在 RAED PHASE 期间更新了数据,如果通过测试那么直接就进入 WRITE PHASE 将所有存在临时变量中的改动全部写入数据库,没有通过测试的事务会直接被终止。

    为了保证乐观并发控制能够正常运行,我们需要知道一个事务不同阶段的发生时间,包括事务开始时间、验证阶段的开始时间以及写阶段的结束时间;通过这三个时间戳,我们可以保证任意冲突的事务不会同时写入数据库,一旦由一个事务完成了验证阶段就会立即写入,其他读取了相同数据的事务就会回滚重新执行。

    作为乐观的并发控制机制,它会假定所有的事务在最终都会通过验证阶段并且执行成功,而锁机制和基于时间戳排序的协议是悲观的,因为它们会在发生冲突时强制事务进行等待或者回滚,哪怕有不需要锁也能够保证事务之间不会冲突的可能。

    多版本并发控制

    MySQL 中实现的多版本两阶段锁协议(Multiversion 2PL)将 MVCC 和 2PL 的优点结合了起来,每一个版本的数据行都具有一个唯一的时间戳,当有读事务请求时,数据库程序会直接从多个版本的数据项中具有最大时间戳的返回。

    MySQL 在InnoDB引擎下有当前读和快照读两种模式。
    1 当前读即加锁读,读取记录的最新版本号,会加锁保证其他并发事物不能修改当前记录,直至释放锁。插入/更新/删除操作默认使用当前读,显示的为select语句加lock in share mode或for update的查询也采用当前读模式。

    2 快照读:不加锁,读取记录的快照版本,而非最新版本,使用MVCC机制,最大的好处是读取不需要加锁,读写不冲突,用于读操作多于写操作的应用,因此在不显示加[lock in share mode]/[for update]的select语句,即普通的一条select语句默认都是使用快照读MVCC实现模式。所以楼主的为了让大家明白所做的演示操作,既有当前读也有快照读……

    • MVCC实现
      MVCC是通过保存数据在某个时间点的快照来实现的. 不同存储引擎的MVCC. 不同存储引擎的MVCC实现是不同的,典型的有乐观并发控制和悲观并发控制.
      InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的,这两个列,分别保存了这个行的创建时间,一个保存的是行的删除时间。这里存储的并不是实际的时间值,而是系统版本号(可以理解为事务的ID),没开始一个新的事务,系统版本号就会自动递增,事务开始时刻的系统版本号会作为事务的ID.

    INSERT
    InnoDB为新插入的每一行保存当前系统版本号作为版本号.

    SELECT
    InnoDB会根据以下两个条件检查每行记录:
    a.InnoDB只会查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的.
    b.行的删除版本要么未定义,要么大于当前事务版本号,这可以确保事务读取到的行,在事务开始之前未被删除.
    只有a,b同时满足的记录,才能返回作为查询结果.

    DELETE
    InnoDB会为删除的每一行保存当前系统的版本号(事务的ID)作为删除标识.

    UPDATE
    InnoDB执行UPDATE,实际上是新插入了一行记录,并保存其创建时间为当前事务的ID,同时保存当前事务ID到要UPDATE的行的删除时间.

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

    千次阅读 2020-07-31 13:45:17
    数据库并发控制机制 数据库的并发控制机制,顾名思义,是用来控制数据库的并发操作的机制。控制的目的是为了保证数据完整和数据一致性。 何为数据一致性?在数据库的并发操作中,多个事务同时读取同一份数据,要...

    数据库并发控制机制

       数据库的并发控制机制,顾名思义,是用来控制数据库的并发操作的机制。控制的目的是为了保证数据完整和数据一致性。
       何为数据一致性?在数据库的并发操作中,多个事务同时读取同一份数据,要保证多个事务读取的同一份数据是准确的。
        可能数据的不一致更好理解。例如事务T1、T2同时更新余额为1000余额表, T1减-100元,更新余额为900元,T2减-500元,更新余额为500元;在T2不知道T1已经更新的情况下直接把余额更新为500元,丢失了T1对余额的更新,此时的数据不能反映真实情况,数据变得不一致。并发事务处理过程中,还可能出现事务T1修改了一条记录,事务T2读取该记录后,事务T1被撤销,此时T2读取的数据就就与数据库中的数据不一致,该数据就为“脏”数据。
       因此并发操作中,需要确保事务的隔离性以保证数据的一致性。那么如何确保事务的隔离性呢?接下来我们对DB2,Mysql和ORACLE三种数据库的并发控制机制比较分析。首先我们先看什么是事务。
    

    数据库的数据一致性支持机制:事务日志

    1. 事务:又称为交易,访问数据库系统的可恢复的最小单元。
      1.1事务的ACID
      原子性(Atomicity):事务为一个整体的工作单元,事务对数据库的操作要么全部执行,要么全部取消。
      一致性(Consistency):事务完成时,所有数据都保持一致状态。
      隔离性(Isolation):事务所做的修改必须与其他事务所做的修改隔离。事务查看数据时数据的状态要么为其他事务修改之前要么为其他事务修改之后,不会为中间状态。即多个事务不能同时修改同一份数据。
      持久性(Durability):事务提交后,对数据库所做的修改会永久保存。

    1.2事务的初始化和终止
    事务在可执行的SQL第一次执行时会自动初始化,事务一旦初始化,就必须终止(COMMIT或ROLLBACK)。
    1.2.1关于事务的COMMIT和ROLLBACK
    多数情况下,事务通过执行COMMIT或ROLLBACK终止事务。执行COMMIT语句后,事务初始化后对数据库做出的所有改变都会变成永久的;执行ROLLBACK语句后,事务初始化后对数据库做出的所有改变都会被撤销,数据库返回事务开始之前的状态。
    1.2.2关于不成功的事务的结果
    上面说了当事务被COMMIT或ROLLBACK终止语句后会发生什么,如果事务完成之前系统发生故障,会发生什么?这种情况下,数据库管理器将撤销所有未COMMIT的修改,从而恢复数据的一致性。
    DB2中通过ACTIVE LOG日志文件实现撤销修改。日志文件包含关于事务执行的每个语句的信息,以及事务是否被成功COMMIT或ROLLBACK的信息。
    Mysql和Oracle利用undo log撤销修改。undo log记录了行的修改操作,执行事务中由于某种原因失败,或使用ROLLBACK时,就可以利用undo log将数据恢复到修改之前的样子。
    1.3事务的隔离级别
    事务为什么需要多种可以设置的隔离级别呢?通常,锁可以实现并发操作中事务的隔离,保证数据的一致性。锁提高了并发性能,但会带来潜在的问题:
    脏读:当前事务可以读到另外一个事务中未提交的数据。
    不可重复读:在一个事务内读到的同一条数据是不一样的。
    幻读:事务A在相同条件下第二次读取时读到新插入的数据。
    丢失更新:一个事务的更新操作会被另一个事务的更新操作所覆盖,从而导致数据的不一致。例如:
    (1)事务T1将行记录修改为V1,事务T1未提交。
    (2)事务T2将行记录修改为V2,事务T2未提交。
    (3)事务T1提交。
    (4)事务T2提交。
    在当前数据库的锁机制下不会导致理论意义上的丢失更新问题,但是实际上在所有多用户计算机系统环境下都有可能产生这个问题。例如:
    (1)事务T1查询一行数据,放入本地内存,显示给User1。
    (2)事务T2查询一行数据,放入本地内存,显示给User2。
    (3)User1修改这行记录,更新数据库并提交。
    (4)User2修改这行记录,更新数据库并提交。
    这些问题往往和系统数据库的使用方式和形态有关。而设置事务的隔离级别,就是根据不同的场景来解决以上问题。比如上面所说的丢失更新问题,隔离级别中SELECT…FOR UPDATE即带有更新意图读的时候,步骤(1)(2)都是要上写锁的,避免了丢失更新的问题。下面详解数据库的隔离级别及其加锁方式。

    SQL标准定义的四个隔离级别为:
    READ UNCOMMITTED:未提交读。事务可以看到其他事务所有未提交的数据。读取数据不加锁。
    READ COMMITTED:提交读。事务只可以看到其他事务已经提交的数据。
    REPEATABLE READ:重复度。锁定事务引用的符合检索条件的部分行,其他事务不可修改这些行,但可执行INSERT操作。即可能出现幻读。
    SERIALIZABLE:可串行化。强制的进行排序,在每个读数据行上添加锁,所有事务依次逐个执行,事务之间不会产生干扰。事务提交后释放锁。会导致大量超时现象和锁竞争。
    四种隔离级别会导致的问题:
    | 隔离级别 | 脏读 | 不可重复读 | 幻读 |
    | READ UNCOMMITTED | √ | √ | √ |
    | READ COMMITTED | × | √ | √ |
    | REPEATABLE READ | × | × | √ |
    | SERIALIZABLE | × | × | × |

    DB2中的隔离级别
    CS(Cursor Stability):游标稳定性。逐行锁定数据,该行数据未修改时,锁定解除,继续加锁读取下一行,该行数据有修改时,则该行锁定持续到事务终止。CS的程序不能查看其他程序未COMMIT的更改。
    CS提供了最大的并发性。但同一事务同一游标被处理两次,可能返回不同的结果,即不可重复度;CS程序读取的行上有任何可更新游标时,其他任何应用程序都不能更新或删除该行。
    CS是DB2默认的隔离级别。在需要最大并行性但只能看到其他程序已COMMIT的数据时使用。
    RR(Repeatable Read):可重复读。RR会锁定事务引用的所有行,直到COMMIT。其他程序不能修改该数据,如果一条数据被访问两次,返回相同的结果。
    RR是最高隔离级别,可以最好的保证数据一致性,但是大量锁定数据,会导致并发度大大降低,同时有可能超过系统定义的持有锁数量的限制。
    相当于标准定义隔离级别中的SERIALIZABLE相比,上锁范围一致。
    RS(Read Stability):读稳定性。RS会锁定事务引用的所有行中符合检索条件的部分行。其他程序不可修改,但可执行INSERT操作,所以同一事务中,如果数据被访问两次可能返回新插入的数据,即幻读,但是旧数据不会有改变。
    相比RR,RS锁定数据的数量大大减少,并发度得到提升。比较适合在并发环境下运行,但只适合在同一事物中不会多次发出相同查询,或不要求相同查询获得相同结果的程序,避免发生幻读。
    DB2的RS和标准定义隔离级别中的REPEATABLE READ(重复读)类似,避免了脏读,但是会出现幻读问题。
    UR(Uncommitted Read):未提交读,也就是“脏”读。UR不会加任何锁,可以读数据库中的任何数据,包含已修改但未COMMIT的数据。读的数据可能与真实的数据有一定差距。
    UR级别最常用于只读表上的查询,或者只执行查询且不关心能否读到其他程序未COMMIT的数据时常用。
    UR相当于标准定义隔离级别中的READ UNCOMMITTED(未提交读)。

    Mysql支持标准定义的四种隔离级别,默认的隔离级别为REPEATABLE READ(重复度),但是与标准SQL不同的是,Mysql的InnoDB存储引擎在REPEATABLE READ的隔离级别下,使用Next-Key Lock(锁定一个范围,并锁定记录本身),因此避免幻读的产生。所以说InnoDB存储引擎在REPEATABLE READ的隔离级别下已经能保证事务的隔离性要求,即达到SQL标准的SERIALIZABLE隔离级别。

    Oracle数据库支持 READ COMMITTED(提交读)和SERIALIZABLE这两种事务隔离级别。默认的隔离级别是READ COMMITTED(提交读)。

    2. 锁
    事务隔离级别是并发控制的整体解决方案,其实际上是综合利用各种类型的锁和行版本控制来解决并发问题。
    这里我们主要看数据库中的基本锁。
    2.1 锁的类型
    S-LOCK:共享锁。又叫读锁,当用户要进行数据的读取时,对数据加上共享锁。共享锁可以同时加多个。
    X-LOCK:排他锁。又叫写锁。SQL INSERT/UPDATE/DELETE语句执行时会上X-LOCK。排他锁只可以加一个,和其他的排他锁共享锁都相斥。
    以上两种类型的锁,DB2,Mysql,Oracle都支持,DB2中还有一种锁U-LOCK。
    U-LOCK:修改锁。CURSOR SELECT 有UPDATE OF 子句时,FETCH时对读出的记录,会上U-LOCK。

    2.2 事务隔离级别中读数据时的锁类型
    如上,数据库在各种隔离级别下,SQL执行 INSERT/UPDATE/DELETE语句时都会上X-LOCK,那么在读数据时如何上锁呢?
    DB2和Mysql在Uncommitted Read隔离级别下,不加任何锁。
    DB2在另外三种CS、RR、RS隔离级别时,SELECT语句,或CURSOR SELECT 无UPDATE OF 子句,FETCH时对读出的记录会上S-LOCK,不同的是,CS在读取下一行数据时就释放上一行的锁,RR、RS在事务提交时才释放锁;SELET…FOR UPDATE对读取的数据都是加U锁,CS在读取下一行数据时就释放上一行的锁,RR、RS在事务提交时才释放锁;INSERT/UPDATE/DELETE语句执行时会上X-LOCK,CS、RR、RS都是在事务提交时才释放X锁,其他事务不能对已锁定的行加任何锁。
    Mysql的InnoDB在隔离级别READ COMMITED 和 REPEATABLE READ(Mysql的默认隔离级别)下SELECT时不上锁,即Mysql中的一致性非锁定读;只有指定SELECT…LOCK IN SHARE MOAD才对记录上S-LOCK,SERIALIZABLE隔离级别下SELECT对记录上S-LOCK;三种隔离级别下,SELET…FOR UPDATE对读取的数据都是加X锁,在Mysql中叫做一致性锁定读。
    Oracle中只支持READ COMMITED和SERIALIZABLE隔离级别。这两种隔离级别下的锁机制和InnoDB一致。Oracle中不需要READ UNCOMMITTED隔离级别,是因为READ UNCOMMITTED主要功能是提高只读时的并发性,而Oracle在READ COMMITED隔离级别下使用一致性非锁定读也有同样的功能。
    2.3 一致性非锁定读
    隔离级别READ COMMITED 和 REPEATABLE READ(Mysql的默认隔离级别)都使用一致性非锁定读, SELECT时不上锁,那么如何保证事务的隔离性呢?这两种隔离级别采用快照数据的方式保证隔离性。读取时对于上了X锁的数据,都会去读取行的一个快照数据。快照数据是指该行的之前版本的数据,通过undo段实现。而undo段用来在事务中回滚数据,因此快照数据本身没有额外的开销。
    READ COMMITED 和 REPEATABLE READ两种隔离级别在读快照数据时的区别是,RC总是读取最新的快照数据,所以可能会发生不可重复读,即第二次读取的数据和第一次不一致;而RR总是读取事务开始时的快照,所以不会发生不可重复度。
    非锁定读机制不会等待行上X锁的释放,极大的提高了数据库的并发性。是InnoDB的默认读取方式。

    3. 小结
    并发控制控制在保证数据一致性的前提下提供最大的并发性,而保证数据一致性的前提就是保证事务的隔离性,事务的隔离性和并发性是成反比的,隔离级别越高,并发性越低。所以程序要视并发性和隔离性的轻重选择隔离级别。

    展开全文
  • Django之数据库并发处理

    千次阅读 2018-08-25 03:38:02
    1.数据库并发处理问题 在多个用户同时发起对同一个数据提交修改操作时(先查询,再修改),会出现资源竞争的问题,导致最终修改的数据结果出现异常。 比如限量商品在热销时,当多个用户同时请求购买商品时,最终...

    1.数据库并发处理问题

    在多个用户同时发起对同一个数据提交修改操作时(先查询,再修改),会出现资源竞争的问题,导致最终修改的数据结果出现异常。

    比如限量商品在热销时,当多个用户同时请求购买商品时,最终修改的数据就会出现异常
    数据库并发处理

    下面我们来写点代码还原一下现象:

    1.新建项目Optimistic locking,创建应用app01,编辑models创建一张表并执行数据库迁移,如下:

    from django.db import models
    
    class GoodsInfo(models.Model):
        """ 商品 """
        name = models.CharField(max_length=50, verbose_name='名称')
        stock = models.IntegerField(default=0, verbose_name='库存')
    
        class Meta:
            db_table = 'tb_goodsinfo'

    2.往数据库中插入一条数据:insert into tb_goodsinfo values(0, "macbook", 10);

    3.定义Goods视图类,

    • 增加判断库存和修改库存之间的间隙,就可以模拟出A用户尚未修改库存之前,B用户已经开始进行判断库存,导致误差:
    from django.http import HttpResponse
    from rest_framework.generics import GenericAPIView
    from app01.models import GoodsInfo
    
    class Goods(GenericAPIView):
        """ 购买商品 """
        def post(self, request):
            # 获取请求头中查询字符串数据
            goods_id = request.GET.get('goods_id')
            count = int(request.GET.get('count'))
    
            # 查询商品对象
            goods = GoodsInfo.objects.filter(id=goods_id).first()
            # 获取原始库存
            origin_stock = goods.stock
    
            # 判断商品库存是否充足
            if origin_stock < count:
                return HttpResponse(content="商品库存不足", status=400)
    
            # 演示多个用户并发请求
            import time
            time.sleep(5)
    
            # 减少商品的库存数量,保存到数据库
            goods.stock = origin_stock - count
            goods.save()
    
            return HttpResponse(content="操作成功", status=200)

    4.定义路由:

    from django.conf.urls import url
    from . import views
    
    urlpatterns =[
        url(r'^goods/$', views.Goods.as_view()),
    ]

    我们先使用postman来模拟单个用户请求

    postman

    • 再来查询数据库,单个用户请求正常,(将stock恢复到10)
      查询数据库

    模拟多个用户请求

    我们来使用两个postman模拟A,B用户同时请求,用户A买6套商品,用户B买5套商品

    运行结果:

    • 输出日志:
      log
    • 查询数据库:
      查询数据库
    • 两个postman发出的post请求均提示 “操作成功”

    分析及结论:

    • 当A用户请求的时候,goods.stock = origin_stock - count
      A操作的结果:goods.stock = 10 - 6 = 4

    • 可是B用户判断库存的时候,A还未将修改的数据保存到数据库,所以B获取的库存数量也是 10
      B操作的结果:goods.stock = 10 - 5 = 5

    • 写入数据库操作中,B的数据将A的数据覆盖,故最后的库存还是 5

    2.解决办法:

    如果使用给数据库加锁的方式,在给处理多个商品时可能会出现死锁,所以使用数据库中的乐观锁方式来处理效果较好

    数据库乐观锁:
    乐观锁并不是真实存在的锁,而是在更新的时候判断此时的库存是否是之前查询出的库存,如果相同,表示没人修改,可以更新库存,否则表示别人抢过资源,不再执行库存更新。类似如下操作

    使用原生的SQL语句
    update tb_goodsinfo set stock=5 where id=1 and stock=10;
    
    使用Django中的语法
    GoodsInfo.objects.filter(id=1, stock=10).update(stock=5)
    
    # GoodsInfo:模型类,  id:商品id,  stock:库存

    改写视图类:

    from django.http import HttpResponse
    from rest_framework.generics import GenericAPIView
    from app01.models import GoodsInfo
    
    class Goods(GenericAPIView):
        """ 购买商品 """
        def post(self, request):
            # 获取请求头中查询字符串数据
            goods_id = request.GET.get('goods_id')
            count = int(request.GET.get('count'))
    
            while True:
                # 查询商品对象
                goods = GoodsInfo.objects.filter(id=goods_id).first()
                # 获取原始库存
                origin_stock = goods.stock
    
                # 判断商品库存是否充足
                if origin_stock < count:
                    return HttpResponse(content="商品库存不足", status=400)
    
                # 演示并发请求
                import time
                time.sleep(5)
    
                # 减少商品的库存数量,保存到数据库
                # goods.stock = origin_stock - count
                # goods.save()
                """ 使用乐观锁进行处理,一步完成数据库的查询和更新 """
                # update返回受影响的行数
                result = GoodsInfo.objects.filter(id=goods.id, stock=origin_stock).update(stock=origin_stock - count)
                if result == 0:
                    # 表示更新失败,有人抢先购买了商品,重新获取库存信息,判断库存
                    continue
    
                # 表示购买成功,退出 while 循环
                break
    
            return HttpResponse(content="操作成功", status=200)

    多用户请求结果:

    • 输出日志:
      log_cuccess
    • 查询数据库
      查询数据库
    • A用户返回 “操作成功”, B用户返回 “商品库存不足”

    3.需要修改MySQL的事务隔离级别

    事务隔离级别指的是在处理同一个数据的多个事务中,一个事务修改数据后,其他事务何时能看到修改后的结果。

    MySQL数据库事务隔离级别主要有四种:

    Serializable 串行化,一个事务一个事务的执行
    
    Repeatable read 可重复读,无论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务影响
    
    Read committed 读取已提交,其他事务提交了对数据的修改后,本事务就能读取到修改后的数据值
    
    Read uncommitted 读取为提交,其他事务只要修改了数据,即使未提交,本事务也能看到修改后的数据值。
    

    MySQL数据库默认使用可重复读( Repeatable read),而使用乐观锁的时候,如果一个事务修改了库存并提交了事务,那其他的事务应该可以读取到修改后的数据值,所以不能使用可重复读的隔离级别,应该修改为读取已提交Read committed。

    修改方法:

    • 打开配置文件
      打开mysql配置文件

    • 修改隔离级别
      修改隔离级别

    OK

    展开全文
  • 数据库思维导图——并发控制 并发控制 多事务执行方式 (1)事务串行执行 每个时刻只有一个事务运行,其他事务必须等到这个事务结束以后方能运行 不能充分利用系统资源,发挥数据库共享资源的特点 (2)交叉并发方式...
  • 多个用户访问同一个数据库时,如果他们的事务同时使用相同的数据,则可能会导致并发问题的产生; 并发操作带来的数据库不一致性可以分为四类:(1)丢失或覆盖更新当两个或多个事务选择同一数据,并且基于最初选定...
  • 数据库并发控制之并发调度

    千次阅读 2018-10-25 01:08:22
    一、并发调度的可串行性 二、两段锁协议 三、封锁的粒度 四、其他并发控制机制
  • 并发操作可能出现的问题 两类丢失更新 脏读 没提交就读到 幻读 如何处理 锁机制: 事务隔离级别 自动加锁 读未提交 – 会发生脏读 读提交 – 会发生不可重复读,不会读到脏数据 可重复读 – 重复读到之前的数据。在...
  • 数据库基础知识及数据库锁概念
  • 并发并行的区别: 并发当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码...
  • 数据库并发控制知识点总结

    千次阅读 2016-08-28 13:13:40
    刚看到一篇很不错的数据库并发控制知识点总结,包括一部分可能会出现在笔试面试中的题目,适合对基础概念理解不透彻的我,就转载过来了。  原文地址:http://blog.csdn.net/xiangminjing/article/details/5922325...
  • 多事务执行方式2.1 事务串行执行2.2 交叉并发方式(Interleaved Concurrency)2.3同时并发方式(simultaneous concurrency)2.4 事务并发执行带来的问题1 并发控制概述1.1修改丢失1.2 不可重复读1.3 读“脏”数据2 ...
  • 数据库并发控制技术

    千次阅读 2018-08-25 14:27:19
    事务是一系列的数据库操作,是数据库应用程序的基本逻辑单元,也是恢复和并发控制的基本单位。 事务处理技术主要包括数据库恢复技术和并发控制技术。本篇博文主要总结下并发控制技术。 事务:是用户定义的一个...
  • 数据库并发带来的问题什么是数据库并发操作带来的问题丢失更新不可重复读读 ' 脏数据 ' 什么是数据库并发操作 用户程序可以一个一个地串行执行,每个时刻只有一个用户程序运行 执行对数据库的存取,其他用户程序必须...
  • 数据库并发操作异常及解决办法

    千次阅读 2020-04-27 12:24:22
    注意同一时间间隔(并发)和同一时刻(并行)的区别。在多道程序环境下,一定时间内,宏观上有多道程序在同时执行,而在每个时刻,单处理机环境下仅有一道程序能够执行,因此微观上这些程序仍是分时交替执行的。操作...
  • 并行数据库 & 分布式数据库

    千次阅读 2019-08-08 09:39:22
    既然决定以后会做与数据相关的研究,就先趁着暑假...并行数据库是新一代高性能数据库系统,是在大规模并行处理计算机和集群并行计算环境的基础上提出。 根据所在的计算机的处理器(Processor)、内存(Memory)及存...
  • 数据库是一个共享资源,可以提供多个用户使用。这些用户程序可以一个一个地串行执行, 每个时刻只有一个用户程序运行, 执行对数据库的存取, 其他用户程序必须等到这个用户程 序结束以后方能对数据库存取。但是...
  • 数据库并发测试

    2012-11-27 11:53:00
    一、数据库并发测试的必要性 1、与数据库连接的服务程序采用多线程同时开启多个数据库连接; 2、与数据库连接的服务程序单线程,但是同时开启多套服务程序; 以上两种情况均会产生对数据库的并发访问操作,数据库...
  • 数据库并发控制

    2018-10-22 10:00:37
    数据库是一个共享资源,允许多个用户同时使用同一个数据库数据库系统称为多用户数据库系统,这样的系统在同一时刻并发运行的事务数可达到数百上千个。 事务可以一个一个地串行执行,即每个时刻只有一个事务进行,...
  • 目录前言一、并发控制概述二、封锁三、封锁协议...事务是并发控制的基本单位,保证事务ACID特性是事物处理的重要任务,而事务的ACID特性可能遭到破坏的原因之一是多个事务对数据库并发操作造成的。为保证事务的隔离性
  • 数据库并发控制

    2020-11-24 17:39:08
    在多用户数据库系统中同一个时刻会有很多个并发运行的事务. 为什么数据库系统要采用并发控制? 1.提高吞吐量和资源利用率: 一个事务由多个步骤组成,一些步骤涉及I/O活动,另一些涉及CPU活动。计算机系统中CPU与...
  • 自ASP.NET诞生以来,微软提供了不少控制并发的方法,在了解这些控制并发的方法前,我们先来简单介绍下并发并发:同一时间或者同一时刻多个访问者同时访问某一更新操作时,会产生并发! 针对并发的处理,又分为...
  • 并行系统中并发问题永远不可忽视。尽管PHP语言原生没有提供多线程机制,那并不意味着所有的操作都是线程安全的。尤其是在操作诸如订单、支付等业务系统中,更需要注意操作数据库并发问题。  接下来我通过一个...
  • 数据库并发机制和事务的隔离级别详解 本文将从以下4个方面来展开: (1)事务的4大特性: (2)数据库并发操作产生的问题: (3)数据库的锁机制: (4)事务的4大隔离级别:
  • 浅谈数据库并发控制

    万次阅读 2018-09-23 19:58:56
    数据库中,并发控制是指在多个用户/进程/线程同时对数据库进行操作时,如何保证事务的一致性和隔离性的,同时最大程度地并发。 当多个用户/进程/线程同时对数据库进行操作时,会出现3种冲突情形: 读-读,不存在...
  • 一、事务的4大特性(ACID) 1. 原子性(Atomicity): 事务是数据库的逻辑工作单位,它对数据库的...并发执行的事务是隔离的,不会相互影响。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每
  • 简述数据库事务并发机制

    万次阅读 多人点赞 2017-04-21 11:17:34
    事务是最小的逻辑执行单元,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务具有四个重要特征,即原子性、一致性、隔离性和持久性。本文首先叙述了数据库中事务...
  • 并发并行及多线程基本概念

    千次阅读 2019-04-11 14:54:55
    并发 并行 同步 异步 多线程
  • 数据库并发调度的可串行性

    千次阅读 2018-10-22 18:44:33
    DBMS对并行事务中各指令的安排执行(调度)是随机的,而不同的调度可能会产生不同的结果。 将所有事务串行执行的调度策略一定是正确的调度策略。 如果错了,一定是事务程序逻辑上的错误,不是因调度而产生的。 以...
  • 数据库并发控制原理详解

    千次阅读 2013-11-28 20:59:47
    数据库并发控制原理 数据库属于公共资源库,当多个事务并发处理数据库数据时,如果控制不当则会造成数据的不一致性,出现数据混乱。对此,数据库引入了锁机制来解决这一问题。为了弄清这个问题,首先要明白为什么多...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 108,352
精华内容 43,340
关键字:

数据库并发并行